나에게 그것은 where
쿼리 의 절이 문제를주는 것으로 보이며 OPTION(RECOMPILE)
사용 되더라도 낮은 추정치의 원인입니다 .
몇 가지 테스트 데이터를 만들었고 결국 두 가지 솔루션이 나타났습니다.이 ID
필드를 resources
변수 (항상 고유 한 경우) 또는 임시 테이블에 저장하면 둘 이상의 값을 가질 수 있습니다 ID
.
기본 테스트 기록
SET NOCOUNT ON
DECLARE @i int= 1;
WHILE @i <= 10000
BEGIN
INSERT INTO [dbo].[Settings]([resourceId],[typeID],remark)
VALUES(@i,@i,'KEPT THESE VALUES OUT BECAUSE IT WOULD CLUTTER THE EXAMPLES, VALUES OVER 8000 Chars entered here'); -- 23254 character length on each value
INSERT INTO [dbo].[Resources](resourceUID)
VALUES(@i);
SET @i += 1;
END
OP (1300 레코드)와 동일한 대략의 결과 집합을 얻으려면 '탐색'값을 삽입하십시오.
INSERT INTO [dbo].[Settings]([resourceId],[typeID],remark)
VALUES(38,38,'KEPT THESE VALUES OUT BECAUSE IT WOULD CLUTTER THE EXAMPLES, VALUES OVER 8000 Chars entered here')
GO 1300
OP와 일치하도록 compat 및 업데이트 통계 변경
ALTER DATABASE StackOverflow SET COMPATIBILITY_LEVEL = 120;
UPDATE STATISTICS settings WITH FULLSCAN;
UPDATE STATISTICS resources WITH FULLSCAN;
원래 검색어
exec sp_executesql N'
select r.id
FROM Resources r
inner join Settings on resourceid=r.id
where resourceUID=@UID
ORDER BY typeID',
N'@UID int',
@UID=38
1300 행이 반환되는 동안 내 예상치가 1 열로 인해 더 나빠 졌습니다. OP가 언급했듯이 추가해도 중요하지 않습니다.OPTION(RECOMPILE)
주목할 점은 where 절을 제거 할 때 추정치가 100 % 정확하다는 것입니다. 두 테이블의 모든 데이터를 사용하므로 예상됩니다.
요점을 증명하기 위해 이전 쿼리에서와 동일한 인덱스를 사용하도록 인덱스를 강요했습니다.
exec sp_executesql N'
select r.id,remark
FROM Resources r with(index([IX_UID]))
inner join Settings WITH(INDEX([IX_Test]))
on resourceid=r.id
ORDER BY typeID',
N'@UID int',
@UID=38
예상대로 좋은 추정치.
그렇다면 더 나은 견적을 얻기 위해 무엇을 바꿀 수 있지만 여전히 가치를 추구 할 수 있습니까?
예를 들어 OP가 제공 한 예제에서와 같이 @UID가 고유 한 경우 변수에서 id
반환 된 단일 resources
변수를 넣은 다음 OPTION (RECOMPILE)을 사용하여 해당 변수를 찾을 수 있습니다.
DECLARE @UID int =38 , @RID int;
SELECT @RID=r.id from
Resources r where resourceUID = @UID;
SELECT @uid, remark
from Settings
where resourceId = @uid
Order by typeID
OPTION(RECOMPILE);
100 % 정확한 추정치
그러나 리소스에 여러 resourceUID가있는 경우 어떻게해야합니까?
테스트 데이터를 추가하십시오
INSERT INTO Resources(ResourceUID)
VALUES (38);
go 50
이것은 임시 테이블로 해결할 수 있습니다
CREATE TABLE #RID (id int)
DECLARE @UID int =38
INSERT INTO #RID
SELECT r.id
from
Resources r where resourceUID = @UID
SELECT @uid, remark
from Settings s
INNER JOIN #RID r
ON r.id =s.resourceId
Order by typeID
OPTION(RECOMPILE)
DROP TABLE #RID
정확한 추정치로 다시 .
이것은 내 자신의 데이터 세트 YMMV로 수행되었습니다.
sp_executesql로 작성
변수로
exec sp_executesql N'
DECLARE @RID int;
SELECT @RID=r.id from
Resources r where resourceUID = @UID;
SELECT @uid, remark
from Settings
where resourceId = @uid
Order by typeID
OPTION(RECOMPILE);',
N'@UID int',
@UID=38
임시 테이블
exec sp_executesql N'
CREATE TABLE #RID (id int)
INSERT INTO #RID
SELECT r.id
from
Resources r where resourceUID = @UID
SELECT @uid, remark
from Settings s
INNER JOIN #RID r
ON r.id =s.resourceId
Order by typeID
OPTION(RECOMPILE)
DROP TABLE #RID',
N'@UID int',
@UID=38
테스트에서 여전히 100 % 정확한 추정치
select r.id, LEFT(remark, 512)
(또는 현명한 부분 문자열 길이).