1

在我向 Microsoft 支持开票之前,我想我会尝试社区!

我有一个正在开发中的应用程序,我们在 SQL 2008 R2(目前是开发人员版)中使用变更数据捕获。对于一些特别复杂的查询,我们希望将查询包装到存储过程中,暴露公共参数,以避免客户端的复杂性(通常的参数)......

在任何情况下,我们已经确定以下语句作为独立查询将在大约 3-5 秒内运行,而不管边界条件如何,而完全相同的语句作为存储过程会跳转到 1.5 分钟产生相同的结果。此外,SP 版本在运行时似乎会在执行过程中多次切换用户身份......此外,在 SP 执行期间,CPU 使用率会飙升。

有什么想法吗?

查询:

DECLARE @fromlsn BINARY(10),
    @tolsn   BINARY(10),
    @NodeID  varchar(6)
SET     @NodeID = '123456',
        @fromlsn = 0x000017E6000001AC0041,
        @tolsn = sys.fn_cdc_get_max_lsn()

DECLARE @min_lsn_TransactionDate BINARY(10),
        @min_TransactionDate smalldatetime

SELECT  @min_TransactionDate = MIN(TransactionDate)
FROM    cdc.fn_cdc_get_net_changes_dbo_tblOrders(sys.fn_cdc_increment_lsn(@fromlsn),@tolsn,'all with merge') 
WHERE   _NODEID_=@NodeId and __$operation<>1

SELECT  @min_lsn_TransactionDate = MIN(__$start_lsn)
FROM    cdc.dbo_tblOrders_CT with (nolock)
WHERE   _NODEID_=@NodeId
    AND TransactionDate=@min_TransactionDate

SELECT   Table1.TransactionDate
    ,Table1.OrderNumber
    ,Table1.SequenceNum 
    ,Table1.ItemNumber
    ,Table1.Quantity
    ,Table1.Price
    ,Table1.ExtPrice
FROM          cdc.fn_cdc_get_net_changes_dbo_tblOrders(sys.fn_cdc_increment_lsn(@fromlsn),@tolsn,'all with mask') Table1
WHERE   Table1._NodeID_=@NodeId
    AND (   Table1.__$operation=2
         OR (   Table1.__$operation=4  
            AND  ( sys.fn_cdc_is_bit_set(9,Table1.__$update_mask)=1 
                   OR sys.fn_cdc_is_bit_set(10,Table1.__$update_mask)=1 
                 )
             )
        )

以及相关的存储过程:

CREATE PROCEDURE testtesttest 
        @fromlsn BINARY(10),
        @tolsn   BINARY(10),
        @NodeID  varchar(10)
as 
DECLARE @min_lsn_TransactionDate BINARY(10),
        @min_TransactionDate smalldatetime

SELECT  @min_TransactionDate = MIN(TransactionDate)
FROM    cdc.fn_cdc_get_net_changes_dbo_tblOrders(sys.fn_cdc_increment_lsn(@fromlsn),@tolsn,'all with merge') 
WHERE   _NODEID_=@NodeId and __$operation<>1

SELECT  @min_lsn_TransactionDate = MIN(__$start_lsn)
FROM    cdc.dbo_tblOrders_CT with (nolock)
WHERE   _NODEID_=@NodeId
    AND TransactionDate=@min_TransactionDate

SELECT   Table1.TransactionDate
    ,Table1.OrderNumber
    ,Table1.SequenceNum 
    ,Table1.ItemNumber
    ,Table1.Quantity
    ,Table1.Price
    ,Table1.ExtPrice
FROM          cdc.fn_cdc_get_net_changes_dbo_tblOrders(sys.fn_cdc_increment_lsn(@fromlsn),@tolsn,'all with mask') Table1
WHERE   Table1._NodeID_=@NodeId
    AND (   Table1.__$operation=2
         OR (   Table1.__$operation=4  
            AND  ( sys.fn_cdc_is_bit_set(9,Table1.__$update_mask)=1 
                   OR sys.fn_cdc_is_bit_set(10,Table1.__$update_mask)=1 
                 )
             )
        )

执行 SP 的脚本:

DECLARE @fromlsn BINARY(10),
    @tolsn   BINARY(10),
    @NodeID  varchar(6)
SET     @NodeID = '123456',
        @fromlsn = 0x000017E6000001AC0041,
        @tolsn = sys.fn_cdc_get_max_lsn()

exec testtesttest @fromlsn,@tolsn,@NodeID

如上文所述,作为查询,大约需要 3-5 秒(在 Management Studio 中)。作为存储过程,1.5 分钟。作为通过 .Net 框架提供程序 (System.Data.SqlClient) 的查询,1.5 分钟。作为通过 OleDb SQLNCLI10 提供程序的查询,3-5 秒。通过 Framework 或 OleDb 作为 SP,1.5 分钟。

有什么想法吗?

4

1 回答 1

0

我的钱将用于缓存中的错误查询计划。尝试刷新过程缓存(不在实时系统上!)或使用 SP 中的 OPTION(重新编译)看看是否有帮助

于 2010-07-22T10:52:21.920 回答