1

ユーザーの入力に従って、フィルタリング、順序付け、およびページングを行う必要があるクエリに取り組んでいます。今、私は本当に遅いケースをテストしています。クエリ プランを調べると、「並べ替え」に 96% の時間がかかっています。

データモデルはそれほど複雑ではありません。次のクエリは、何が起こっているかを理解するのに十分明確です。

WITH OrderedRecords AS (
    SELECT 
        A.Id
        , A.col2
        , ...
        , B.Id
        , B.col1 
        , ROW_NUMBER() OVER (ORDER BY B.col1 ASC) AS RowNumber
    FROM A
    LEFT JOIN B ON (B.SomeThing IS NULL) AND (A.BId = B.Id)
    WHERE (A.col2 IN (...)) AND (B.Id IN (...))
)
SELECT
    *
FROM OrderedRecords WHERE RowNumber Between x AND y

A は約 10 万件のレコードを含むテーブルですが、フィールド内で数千万件に増加します。一方、B は 5 つの項目を持つカテゴリ タイプのテーブルです (これは、おそらくそれ以上に大きくなることはありません)。A.Id と B.Id にはクラスター化インデックスがあります。

パフォーマンスは本当にひどいので、どうにかしてこれを改善できないかと考えています。たとえば、順序が B.col1 ではなく A.Id にある場合、すべてが非常に高速です。おそらく、B.col1 はある種のインデックスを最適化できます。

フィールド自体にインデックスを付けようとしましたが、これは役に立ちませんでした。おそらく、テーブル B の個別の項目の数が非常に少ないためです (それ自体および A と比較して)。

何か案は?

4

2 に答える 2

1

これが問題の一部である可能性があると思います:

   LEFT JOIN B ON (B.SomeThing IS NULL) AND (A.Id = B.Id)
    WHERE (A.col2 IN (...)) AND (B.Id IN (...)

特定の B.ID 行のみが返されるため、LEFT JOIN は論理的に INNER JOIN のように機能します。これは、WHERE 句が配置されているためです。それがあなたの意図である場合は、先に進んで内部結合を使用してください。これにより、制限された数の行を探していることをオプティマイザーが認識するのに役立つ場合があります。

于 2013-10-30T13:27:46.367 に答える
0

以下を試してみることをお勧めします。

Bテーブル作成インデックスの場合:

create index IX_B_1 on B (col1, Id, SomeThing)

Aテーブル作成インデックスの場合:

create index IX_A_1 on A (col2, BId) include (Id, ...)

CTEにリストされている表の他のincludeすべての列を入れます。ASELECTOrderedRecords

ただし、ご覧のとおり、インデックスIX_A_1はスペースを取り、テーブルデータ自体のサイズを取ることができます。

したがって、別の方法としてinclude、インデックスの一部から余分な列を省略してみてください。

create index IX_A_2 on A (col2, BId) include (Id)

ただし、この場合、クエリを少し変更する必要があります。

;WITH OrderedRecords AS (
    SELECT 
        AId = A.Id
        , A.col2
        -- remove other A columns from here
        , bid = B.Id
        , B.col1 
        , ROW_NUMBER() OVER (ORDER BY B.col1 ASC) AS RowNumber
    FROM A
    LEFT JOIN B ON (B.SomeThing IS NULL) AND (A.BId = B.Id)
    WHERE (A.col2 IN (...)) AND (B.Id IN (...))
)
SELECT
    R.*, A.OtherColumns
FROM OrderedRecords R
    join A on A.Id = R.AId
WHERE R.RowNumber Between x AND y
于 2013-10-30T15:07:43.787 に答える