SQL 2008 更改数据捕获查询性能问题(SP 与直接查询)

发布于 2024-09-05 12:23:40 字数 3296 浏览 10 评论 0原文

在向 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 分钟。

有什么想法吗?

Before I open a ticket with Microsoft Support, I thought I'd try the community!

I have an application in development for which we are using Change Data Capture in SQL 2008 R2 (developer edition, currently). For some particularly complex queries, we wanted to wrap the queries into stored procedures, exposing common parameters, to avoid complexity in the client (the usual argument)...

In any case, what we've identified is that the following statement, as a standalone query, will run in about 3-5 seconds, regardless of the boundary conditions, whereas the exact same statement, as a stored procedure, jumps to 1.5 minutes to produce the same results. In addition, the SP version while running seems to switch user identities several times over the course of execution... Also, during execution of the SP, the CPU usage spikes.

Any thoughts?

The Query:

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 
                 )
             )
        )

And the associated Stored Procedure:

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 
                 )
             )
        )

Script to execute the 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

As indicated in the text above, as a Query, it takes abuot 3-5 seconds (in Management Studio). As a Stored Proceure, 1.5 minutes. As a query via the .Net framework providor (System.Data.SqlClient), 1.5 minutes. As a query via the OleDb SQLNCLI10 provider, 3-5 seconds. As an SP via either Framework or OleDb, 1.5 minutes.

Any thoughts?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

何必那么矫情 2024-09-12 12:23:40

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

My money would be on a bad query plan in the cache. Try either flushing the procedure cache (not on a live system!) or using the OPTION (Recompile) in the SP to see if that helps

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文