Diberikan tabel bentuk umum berikut:
CREATE TABLE Device
(
ID integer PRIMARY KEY
);
CREATE TABLE EventType
(
ID integer PRIMARY KEY,
Name nvarchar(50) NOT NULL
);
CREATE TABLE [Event]
(
ID integer PRIMARY KEY,
[TimeStamp] datetime NOT NULL,
EventTypeID integer NOT NULL REFERENCES EventType,
DeviceID integer NOT NULL REFERENCES Device
);
Indeks berikut bermanfaat:
CREATE INDEX f1
ON [Event] ([TimeStamp], EventTypeID)
INCLUDE (DeviceID)
WHERE EventTypeID IN (2, 5, 7, 8, 9, 14);
Untuk kueri:
SELECT
[Event].ID,
[Event].[TimeStamp],
EventType.Name,
Device.ID
FROM
[Event]
INNER JOIN EventType ON EventType.ID = [Event].EventTypeID
INNER JOIN Device ON Device.ID = [Event].DeviceID
WHERE
[Event].[TimeStamp] BETWEEN '2011-01-28' AND '2011-01-29'
AND Event.EventTypeID IN (2, 5, 7, 8, 9, 14);
Filter memenuhi AND
persyaratan klausa, kunci pertama indeks memungkinkan pencarian [TimeStamp]
untuk difilter EventTypeIDs
dan termasuk DeviceID
kolom membuat indeks meliputi (karena DeviceID
diperlukan untuk bergabung ke Device
tabel).
Kunci kedua dari indeks - EventTypeID
tidak sepenuhnya diperlukan (bisa juga berupa INCLUDEd
kolom); Saya telah memasukkannya ke dalam kunci karena alasan yang disebutkan di sini . Secara umum, saya menyarankan orang untuk setidaknya INCLUDE
kolom dari WHERE
klausa indeks yang difilter .
Berdasarkan permintaan yang diperbarui dan rencana eksekusi dalam pertanyaan, saya setuju bahwa indeks yang lebih umum yang disarankan oleh SSMS kemungkinan adalah pilihan yang lebih baik di sini, kecuali daftar yang difilter EventTypeIDs
bersifat statis karena Aaron juga menyebutkan dalam jawabannya:
CREATE TABLE Device
(
ID integer PRIMARY KEY,
Name nvarchar(50) NOT NULL UNIQUE
);
CREATE TABLE EventType
(
ID integer PRIMARY KEY,
Name nvarchar(20) NOT NULL UNIQUE,
[Description] nvarchar(100) NOT NULL
);
CREATE TABLE [Event]
(
ID integer PRIMARY KEY,
PLCTimeStamp datetime NOT NULL,
EventTypeID integer NOT NULL REFERENCES EventType,
DeviceID integer NOT NULL REFERENCES Device,
IATA varchar(50) NOT NULL,
Data1 integer NULL,
Data2 integer NULL,
);
Indeks yang disarankan (nyatakan unik jika sesuai):
CREATE UNIQUE INDEX uq1
ON [Event]
(EventTypeID, PLCTimeStamp)
INCLUDE
(DeviceID, IATA, Data1, Data2, ID);
Informasi kardinalitas dari rencana eksekusi (sintaksis tidak berdokumen, jangan gunakan dalam sistem produksi):
UPDATE STATISTICS dbo.Event WITH ROWCOUNT = 4042700, PAGECOUNT = 400000;
UPDATE STATISTICS dbo.EventType WITH ROWCOUNT = 22, PAGECOUNT = 1;
UPDATE STATISTICS dbo.Device WITH ROWCOUNT = 2806, PAGECOUNT = 28;
Kueri yang diperbarui (mengulangi IN
daftar untuk EventType
tabel membantu pengoptimal dalam kasus khusus ini):
SELECT
Event.ID,
Event.IATA,
Device.Name,
EventType.Description,
Event.Data1,
Event.Data2,
Event.PLCTimeStamp,
Event.EventTypeID
FROM
Event
INNER JOIN EventType ON EventType.ID = Event.EventTypeID
INNER JOIN Device ON Device.ID = Event.DeviceID
WHERE
Event.EventTypeID IN (3, 30, 40, 41, 42, 46, 49, 50)
AND EventType.ID IN (3, 30, 40, 41, 42, 46, 49, 50)
AND Event.PLCTimeStamp BETWEEN '2011-01-28' AND '2011-01-29'
AND Event.IATA LIKE '%0005836217%'
ORDER BY Event.ID;
Perkiraan rencana eksekusi:
Paket yang Anda dapatkan kemungkinan akan berbeda karena saya menggunakan statistik dugaan. Poin umumnya adalah memberikan pengoptimal sebanyak mungkin informasi, dan memberikan metode akses (indeks) yang efisien pada [Event]
tabel 4-juta baris .