4

インデックスが破損しているように見えるものがありますか?

これが何が起こっているかです。私は 2 つのテーブル関数を持っています。1 つ目はケースのセットで、2 つ目は日付のセットです。これらの 2 つのセットには、1 (ケース) 対 0 または 1 (認識日) の関係があります。通常、私はそれらを次のようにクエリします。

SELECT c.CaseID, a.AwareDate  
FROM Cases(@date) AS c  
LEFT JOIN AwareDates(@date) AS a ON c.CaseID = a.CaseID;

問題は、一致する AwareDates のすべての行が JOIN されているように見えないことです。結合ヒントを追加すると、それらは実行されます。いう;

SELECT c.CaseID, a.AwareDate  
FROM Cases(@date) AS c  
LEFT MERGE JOIN AwareDates(@date) AS a ON c.CaseID = a.CaseID;

クエリ プランから気付いたのは、結合ヒントを追加すると、結合の前に AwareDate データの一種が追加されることです。これは、他の方法では存在しません。また、クエリ プランナーは、ヒントがない場合、結合を RIGHT OUTER JOIN に切り替えます。もちろん、ヒントが存在する場合は LEFT JOIN を保持します。

エラーが検出されずに次のことを行いました。

DBCC UPDATEUSAGE (0) WITH INFO_MESSAGES, COUNT_ROWS;  
EXECUTE sp_updatestats 'resample';  
DBCC CHECKDB (0) WITH ALL_ERRORMSGS, EXTENDED_LOGICAL_CHECKS;  

私は困惑しています...何かアイデアはありますか?

UDF の定義は次のとおりです。

ALTER FUNCTION dbo.Cases( @day date ) RETURNS TABLE
WITH SCHEMABINDING
AS RETURN (
SELECT 
    CaseID -- other 42 columns ommitted
FROM (
    SELECT
        ROW_NUMBER() OVER (PARTITION BY CaseID ORDER BY UpdateDate DESC, UpdateNumber DESC) AS RecordAge,
        CaseID, 
        Action
    FROM
        dbo.CaseAudit
    WHERE
        convert(date,UpdateDate) <= @day
    ) AS History
WHERE
    RecordAge = 1                    -- only the most current record version
    AND isnull(Action,'') != N'DEL'  -- only include cases that have not been deleted
)

ALTER FUNCTION dbo.AwareDates( @day date ) RETURNS TABLE
WITH SCHEMABINDING
AS RETURN (
WITH 
    History AS (
        SELECT row_number() OVER (PARTITION BY CaseID, ContactID ORDER BY UpdateDate DESC, UpdateNumber DESC) AS RecordAge,
            CaseID, InfoReceived, ReceiveDate, ResetClock, Action
        FROM dbo.ContactLogAudit WITH (NOLOCK)
        WHERE convert(date,UpdateDate) <= @day
        ),
    Notes AS (
        SELECT 
            CaseID,
            convert(date,ReceiveDate,112) AS ReceiveDate,
            ResetClock
        FROM History 
        WHERE RecordAge = 1                -- only the most current record version
        AND isnull(Action,'') != N'DEL'    -- only include notes that have not been deleted
        AND InfoReceived = N'Y'            -- only include notes that have Info Rec'd checked 
        AND len(ReceiveDate) = 8 AND isnumeric(ReceiveDate) = 1 AND isdate(ReceiveDate) = 1 -- only include those with a valid aware date
        ),
    Initials AS (
        SELECT CaseID, min(ReceiveDate) AS ReceiveDate
        FROM Notes 
        GROUP BY CaseID
        ),
    Resets AS (
        SELECT CaseID, max(ReceiveDate) AS ReceiveDate
        FROM Notes 
        WHERE ResetClock = N'Y'
        GROUP BY CaseID
        )
SELECT 
    i.CaseID                              AS CaseID,
    i.ReceiveDate                         AS InitialAwareDate, -- the oldest valid aware date value (must have AE Info Reveived checked and a received date)
    coalesce(r.ReceiveDate,i.ReceiveDate) AS AwareDate  -- either the newest valid aware date value with the Reset Clock checked, otherwise the initial aware date value
FROM Initials AS i
LEFT JOIN Resets AS r 
    ON i.CaseID = r.CaseID
);

さらに、「WITH (NOLOCK)」テーブル ヒントを削除すると、正しい結果が得られることがわかりました。また、結合ヒントを AwareDates UTF に追加するか、イニシャルとリセットの間の LEFT JOIN 関係に COLLATE Latin1_General_BIN を追加する場合。


クエリ プランの行数 -- 結合ヒントなし (破損)

  • ケース { 実績: 25,891、推定: 19,071.9 }
  • AwareDates { 実際: 24,693、推定: 1,463.09 }
    • イニシャル { 実際: 24,693、推定: 1,463.09 }
    • 残り { 実際: 985、推定: 33.2671 }
  • AwareDates は、結合された結果セットの 8,108 行の Cases と一致します

クエリ プランの行数 -- 結合ヒントあり (動作中)

  • ケース { 実績: 25,891、推定: 19,071.9 }
  • AwareDates { 実際: 24,673、推定: 1,837.67 }
    • イニシャル { 実際: 24,673、推定: 1,837.67 }
    • 残り { 実際: 982、推定: 42.6238 }
  • AwareDates は、結合された結果セットの 24,673 行の Cases と一致します

問題の範囲をさらに絞り込みました。できます;

SELECT * FROM AwareDate(@date);  

SELECT * FROM AwareDate(@date) ORDER BY CaseID;  

行数が異なります。

4

1 に答える 1

2

SQLの特定のバージョン(@@ version)を指定していませんが、これはSQL 2008R2の累積的な更新6で修正されたバグのように疑わしいようです(明らかにSQL 2008にも適用されます)。

KB 2433265
修正:SQL Server 2008でROW_NUMBER関数を左外部結合と一緒に使用するクエリを実行すると、誤った結果が表示される場合があります

この記事の例では、DISTINCTを指定しています。ただし、この記事はあいまいに表現されています。明確なものが必要かどうか、またはDISTINCTがトリガーの1つであるかどうかは明確ではありません。

あなたの例には記事のような明確なものはありませんが、質問をするために変更されているように見えます(つまり、42列が欠落しています)。明確なものはありますか?また、AwareDatesudfでは、InitialsCTEに到達するまでに、DISTINCTと同じ効果を持つ可能性のあるGROUPBYを実行します。


アップデート

@DennisのコメントからSQL20080と2008R2のどちらを使用しているかはまだわかりません。

2008を実行している場合、KBの記事には、「この問題の修正は、SQL Server 2008 ServicePack1の累積的な更新プログラム11で最初にリリースされました」と記載されています。したがって、SP1を投稿します。

一方、SQL 2008 R2を使用している場合は、これがSP1の一部であるCU6で修正されたことは正しいです。しかし、このバグは再び表面化したようです。SQL Server 2008 R2 ServicePack1の累積的な更新パッケージ4を見てください-SP1以降にリリースされました。

970198      FIX: You receive an incorrect result when you run a 
            query that uses the row_number function in SQL Server 2008 
            or in SQL Server 2008 R2 

関連するKB記事で、MSはdistinctへの参照を削除しました。

Consider the following scenario. You run a query against a table that has a 
clustered index in Microsoft SQL Server 2008 or in Microsoft SQL Server 2008
R2. In the query, you use the row_number function. In this scenario, you 
receive an incorrect result when a parallel execution plan is used for the 
query. If you run the query many times, you may receive different results.

これは、KB 2433265を以前に読んだことを裏付けているようです。この言い回しは、明確な表現は、動作を引き起こす可能性のある多くの条件の1つにすぎないことを示唆しています。今回は並行実行計画が原因のようです。

于 2012-03-23T01:49:58.113 に答える