要件は、テーブル「empl」の 65 列すべてを最小 IOでページングに 50 レコードをロードすることです。テーブルには 280000 件以上のレコードがあります。PK 上のクラスター化インデックスは 1 つだけです。
ページネーションクエリは次のとおりです。
WITH result_set AS (
SELECT
ROW_NUMBER() OVER (ORDER BY e.[uon] DESC ) AS [row_number], e.*
FROM
empl e with (NOLOCK)
LEFT JOIN empl_add ea with (NOLOCK)
ON ea.ptid = e.ptid
WHERE
e.del = 0 AND e.pub = 1 AND e.sid = 2
AND e.md = 0
AND e.tid = 3
AND e.coid = 2
AND (e.cid = 102)
AND ea.ptgid IN (SELECT ptgid FROM empl_dep where psid = 1001
AND ib = 1))
SELECT
*
FROM
result_set
WHERE
[row_number] BETWEEN 0 AND 50
以下は、プロファイラーから上記のクエリを実行した後の統計です。
CPU: 1500、読み取り: 25576、期間: 25704
次に、テーブル empl に次のインデックスを配置します。
CREATE NONCLUSTERED INDEX [ci_empl]
ON [dbo].[empl] ([del],[md],[pub],[tid],[coid],[sid],[ptid],[cid],[uon])
GO
インデックスを配置した後、CPU と読み取りはさらに高くなります。インデックスのどこが悪いのか、クエリのどこが悪いのかわかりませんか?
編集:
次のクエリも、インデックスを配置した後に高い読み取りを行っています。そして、3 つの列と 1 つのカウントしかありません。
SELECT TOP (2147483647)
ame.aid ID, ame.name name,
COUNT(empl.pid) [Count], ps.uff uff FROM ame with (NOLOCK)
JOIN pam AS pa WITH (NOLOCK) ON pa.aid = ame.aid
JOIN empl WITH (NOLOCK) ON empl.pid = pa.pid
LEFT JOIN psam AS ps
ON ps.psid = 1001
AND ps.aid = ame.aid
LEFT JOIN empl_add ea with (NOLOCK)
ON ea.ptid = empl.ptid
WHERE
empl.del = 0 AND empl.pub = 1 AND empl.sid = 2
AND empl.md = 0
AND (empl.tid = 3)
AND (empl.coid = 2)
AND (empl.cid = 102)
AND ea.ptgid IN (SELECT ptgid FROM empl_dep where psid = 1001
AND ib = 1)
AND ame.pub = 1 AND ame.del = 0
GROUP BY ame.aid, ame.name, ps.uff
ORDER BY ame.name ASC
2番目の編集:
これで、「uon」列に次のインデックスを配置しました。
CREATE NONCLUSTERED INDEX [ci_empl_uon]
ON [dbo].[empl] (uon)
GO
しかし、それでも CPU と読み取りは高くなっています。
3 番目の編集:
DTA は、最初のクエリにすべての列を含むインデックスを提案しているので、提案されたインデックスを変更して、基本的な 4 つのフィルターのフィルター インデックスに変換し、より効果的にしました。
インデックスの作成中にインクルードの後に以下の行を追加しました。
Where e.del = 0 AND e.pub = 1 AND e.sid = 2 AND e.md = 0 AND e.coid = 2
それでも、開発マシンと本番マシンの両方で読み取りが高くなっています。
4番目の編集:
今、私はパフォーマンスを改善するソリューションにたどり着きましたが、それでも目標には達していません. 重要なのは、それがALL THE DATAではないということです。
クエリは次のとおりです。
WITH result_set AS (
SELECT
ROW_NUMBER() OVER (ORDER BY e.[uon] DESC ) AS [row_number], e.pID pID
FROM
empl e with (NOLOCK)
LEFT JOIN empl_add ea with (NOLOCK)
ON ea.ptid = e.ptid
WHERE
e.del = 0 AND e.pub = 1 AND e.sid = 2
AND e.md = 0
AND e.tid = 3
AND e.coid = 2
AND (e.cid = 102)
AND ea.ptgid IN (SELECT ptgid FROM empl_dep where psid = 1001
AND ib = 1))
SELECT
*
FROM
result_set join empl on result_set.pID = empl.pID
WHERE
[row_number] BETWEEN @start AND @end
キー列を変更してインデックスを再作成し、インクルードとフィルター処理を行います。
CREATE NONCLUSTERED INDEX [ci_empl]
ON [dbo].[empl] ([ptid],[cid],[tid],[uon])
INCLUDE ([pID])
Where
[coID] = 2 and
[sID] = 2 and
[pub] = 1 and
[del] = 0 and
[md] = 0
GO
パフォーマンスは向上しますが、目標には達しません。