DB に負荷が発生した後、クエリの 1 つが低下しました。
私たちのクエリは、3 つのテーブル間の結合です。
Base
10 M 行を含むテーブル。EventPerson
5000行を含むテーブル。EventPerson788
空です。
EventPerson
オプティマイザーは、シークではなく、問題を再現するためのスクリプトでインデックスをスキャンしているようです。
--Create Tables
CREATE TABLE [dbo].[BASE](
[ID] [bigint] NOT NULL,
[IsActive] BIT
PRIMARY KEY CLUSTERED ([ID] ASC)
)ON [PRIMARY]
GO
CREATE TABLE [dbo].[EventPerson](
[DUID] [bigint] NOT NULL,
[PersonInvolvedID] [bigint] NULL,
PRIMARY KEY CLUSTERED ([DUID] ASC)
) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [EventPerson_IDX] ON [dbo].[EventPerson]
(
[PersonInvolvedID] ASC
)
CREATE TABLE [dbo].[EventPerson788](
[EntryID] [bigint] NOT NULL,
[LinkedSuspectID] [bigint] NULL,
[sourceid] [bigint] NULL,
PRIMARY KEY CLUSTERED ([EntryID] ASC)
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[EventPerson788] WITH CHECK
ADD CONSTRAINT [FK7A34153D3720F84A]
FOREIGN KEY([sourceid]) REFERENCES [dbo].[EventPerson] ([DUID])
GO
ALTER TABLE [dbo].[EventPerson788] CHECK CONSTRAINT [FK7A34153D3720F84A]
GO
CREATE NONCLUSTERED INDEX [EventPerson788_IDX]
ON [dbo].[EventPerson788] ([LinkedSuspectID] ASC)
GO
--POPOLATE BASE TABLE
DECLARE @I BIGINT=1
WHILE (@I<10000000)
BEGIN
begin transaction
INSERT INTO BASE(ID) VALUES(@I)
SET @I+=1
if (@I%10000=0 )
begin
commit;
end;
END
go
--POPOLATE EventPerson TABLE
DECLARE @I BIGINT=1
WHILE (@I<5000)
BEGIN
BEGIN TRANSACTION
INSERT INTO EventPerson(DUID,PersonInvolvedID) VALUES(@I,(SELECT TOP 1 ID FROM BASE ORDER BY NEWID()))
SET @I+=1
IF(@I%10000=0 )
COMMIT TRANSACTION ;
END
GO
これはクエリです:
select
count(EventPerson.DUID)
from
EventPerson
inner loop join
Base on EventPerson.DUID = base.ID
left outer join
EventPerson788 on EventPerson.DUID = EventPerson788.sourceid
where
(EventPerson.PersonInvolvedID = 37909 or
EventPerson788.LinkedSuspectID = 37909)
AND BASE.IsActive = 1
オプティマイザーがインデックス シークの代わりにインデックス スキャンを使用することを決定した理由がわかりましたか?
すでに行われている回避策:
- テーブルを分析し、統計を作成します。
- インデックスを再構築します。
- FORCESEEK ヒントを試す
EventPerson
上記のいずれも、オプティマイザーがベース テーブルに対して インデックス シークとシークを実行するよう説得するものではありませんでした。
ご協力いただきありがとうございます 。