테이블 "empl"의 65 개 열 모두가 페이징에 최소 IO로로드되도록 요구 사항이로드됩니다. 테이블에는 280000+ 개의 레코드가 있습니다. PK를 통해 클러스터 된 인덱스는 하나뿐입니다. CPU인덱스를 넣은 후 읽기가 낮아지지 않습니다.
: 1500 읽습니다 : 25576, 소요 시간 :
매김 쿼리는 다음과 같습니다 : 프로파일에서 위의 쿼리를 실행 한 후 통계
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
다음은 그런 25,704
내가 테이블 empl에 다음 색인을 붙여 넣으십시오.
어미스트 퍼팅 인덱스 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
두 번째 편집 :
지금은 "UON"열에서 다음 인덱스를 넣어했다 :
CREATE NONCLUSTERED INDEX [ci_empl_uon]
ON [dbo].[empl] (uon)
GO
하지만 여전히 CPU와 높은 읽습니다.
세 번째 편집 :
모든 열이 첫 번째 쿼리에 포함와 내가 제안 된 인덱스를 만들기 위해 기본 4 개 개의 필터에 대한 필터 인덱스로 변환 변경 DTA 나에게 인덱스를 제안한다것이 더 효과적 .
다음 줄을 추가하여 색인을 만드는 동안을 포함시킵니다.
그러나 개발 및 프로덕션 컴퓨터에서 여전히 읽기가 높습니다.
넷째 편집 :
은 지금은하지 최대 목표로 여전히 성능을 개선하는 솔루션에 와서 만했다. 열쇠는 그것이 가려고하지 않는다는 것입니다. 모든 데이터.
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
그것은 성능을 향상 아니라 목표까지
쿼리는이 다음이다.
'SELECT *'를 사용하여 테이블에서 ** 모든 ** 열을 선택한다. - SQL 엔진이 비 클러스터형 인덱스의 데이터 페이지 (클러스터 된 인덱스)로 되돌아 가야 ** 모든 ** 열을 가져올 수 있기 때문에 인덱스가 도움이되지 않을 수 있습니다. 종종 쿼리 최적화 프로그램이 ** (클러스터 된) 인덱스 스캔 **을 사용하게합니다 ** –
열이 읽기 수를 줄입니까? 인덱스가 테이블보다 적은 데이터를 저장한다고 생각하십니까? 왜 그랬을까요? * 모든 * 데이터의 복사본이 포함되어 있습니다! 내 음악 라이브러리를 두 번째 컴퓨터에 복사하면 디스크 공간을 덜 차지해야합니까? –
@Aaron : 색인은 키 열에 만 사용되며 모든 열에는 사용되지 않습니다. – Prakash