다음과 같은 일반적인 형식의 테이블이 제공됩니다.
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
);
다음 색인이 유용합니다.
CREATE INDEX f1
ON [Event] ([TimeStamp], EventTypeID)
INCLUDE (DeviceID)
WHERE EventTypeID IN (2, 5, 7, 8, 9, 14);
쿼리의 경우 :
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);
필터는 AND
절의 요구 사항을 충족하며 , 인덱스의 첫 번째 키 [TimeStamp]
는 필터링 된 검색을 허용 EventTypeIDs
하고 DeviceID
열을 포함하여 인덱스를 덮습니다 ( 테이블에 DeviceID
조인하는 데 필요하기 때문에 Device
).
인덱스의 두 번째 키 EventTypeID
는 꼭 필요한 것은 아닙니다 ( INCLUDEd
열일 수도 있음 ). 여기에 언급 된 이유로 키 에 포함 시켰습니다 . 일반적으로 필터링 된 인덱스 절의 열을 사람들에게 권합니다 .INCLUDE
WHERE
질문의 업데이트 된 쿼리 및 실행 계획을 기반으로, EventTypeIDs
Aaron이 자신의 답변에서 언급 한 것처럼 필터링 된 목록 이 정적 인 경우가 아니라면 SSMS가 제안한보다 일반적인 색인이 여기에서 더 나은 선택 일 것입니다.
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,
);
제안 된 색인 (적절한 경우 고유 한 것으로 선언) :
CREATE UNIQUE INDEX uq1
ON [Event]
(EventTypeID, PLCTimeStamp)
INCLUDE
(DeviceID, IATA, Data1, Data2, ID);
실행 계획의 카디널리티 정보 (문서화되지 않은 구문, 프로덕션 시스템에서는 사용하지 않음) :
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;
업데이트 된 쿼리 ( 테이블 의 IN
목록을 반복하면 EventType
이 특정 경우 옵티 마이저에 도움이 됨) :
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;
예상 실행 계획 :
내가 추측 한 통계를 사용하고 있기 때문에 계획이 다를 수 있습니다. 일반적인 요점은 옵티 마이저에게 가능한 많은 정보를 제공하고 4 백만 행 [Event]
테이블 에 효율적인 액세스 방법 (인덱스)을 제공하는 것 입니다.