2017-02-04 4 views
0

현재 비트 필드 연산자를 사용하여 작업을 분류하기 위해 정수 필드를 사용하는 SQL Server 데이터베이스로 작업하고 있습니다.SQL Server 2016 - 비트 대 복수 비트 열

필자는 성능 병목 현상이라고 생각하여이 열을 여러 개의 인덱싱 된 비트 열로 나누기 시작했습니다. 그러나 몇 가지 테스트를 한 후에 나는 특별한 결과를 발견했습니다. 비트 별 쿼리는 비트 열보다 성능이 우수합니다.

내 두 쿼리 내가 테스트하고 있습니다 ...

declare @HotJob int = 32; 
declare @FeaturedJob int = 64; 

select * from Job 
where (JobType&@HotJob)[email protected] 
and (JobType&@FeaturedJob)=0; 

select * from Job 
where HotJob = 1 
and FeaturedJob = 0; 

쿼리 분석기는 상대적으로 비용이 28 % ~ 72 %임을보고 있습니다.

테이블 크기는 25K 행으로 비교적 작습니다.

누구나 이것이 왜 그런지 제안 할 수 있습니까?

비트 열을 유지하는 데 아무런 문제가 없지만 정확히 읽는 것이 개별 열이 더 잘 작동해야한다는 것을 알았을 때 왜 더 정확하게 수행되는지 궁금했습니다.

+0

이러한 쿼리 계획을 살펴 보셨습니까? 두 번째 사람이 핵심 조회를 끝내는 것처럼 느껴지지만, 나는 결코 노력하지 않고 그것을 reprove 수 없습니다. –

+0

bitwise 쿼리의 경우 키 조회 및 인덱스 스캔을 수행합니다. 비 비트 쿼리의 경우 클러스터 된 인덱스 스캔 만 수행합니다. – user1751825

+0

여러 가지 다른 수의 조합을 사용하여 여러 열을 반환했지만 차이가 항상 중요하지는 않지만 비트 단위 버전은 항상 비용이 적게 듭니다. – user1751825

답변

0

여러 열에 액세스하는 오버 헤드가 단일 열의 오버 헤드보다 큰 것 같습니다. 그러나 정규화 된 열을 사용하면 전체 스캔을 피하면서 유용한 인덱스를 만들 수 있습니다. 상대적인 비용 (염분으로 섭취하는)은 아래의 커버 링 지수 예와 함께 91 %와 9 %입니다. 최적의 색인 생성은 검색어 및 데이터에 따라 달라 지므로 실험을해야 할 수도 있습니다.

CREATE TABLE dbo.JobBitMask(
     JobID int NOT NULL 
     CONSTRAINT PK_JobBitMask PRIMARY KEY 
    , JobType int NOT NULL 
    , JobData varchar(100) NOT NULL 
    ); 

WITH 
    t4 AS (SELECT n FROM (VALUES(0),(0),(0),(0)) t(n)) 
    ,t256 AS (SELECT 0 AS n FROM t4 AS a CROSS JOIN t4 AS b CROSS JOIN t4 AS c CROSS JOIN t4 AS d) 
    ,t16M AS (SELECT ROW_NUMBER() OVER (ORDER BY (a.n)) AS num FROM t256 AS a CROSS JOIN t256 AS b CROSS JOIN t256 AS c) 
INSERT INTO dbo.JobBitMask WITH (TABLOCKX) (JobID, JobType, JobData) 
SELECT num, CASE num%10 WHEN 0 THEN 32 ELSE 0 END + CASE num%3 WHEN 0 THEN 64 ELSE 0 END, 'other data' 
FROM t16M 
WHERE num <= 25000; 

CREATE TABLE dbo.JobNormalized(
     JobID int NOT NULL 
     CONSTRAINT PK_JobNormalized PRIMARY KEY 
    , HotJob bit NOT NULL 
    , FeaturedJob bit NOT NULL 
    , JobData varchar(100) NOT NULL 
    ); 
CREATE INDEX idx1 ON dbo.JobNormalized(HotJob, FeaturedJob) INCLUDE(JobData); 

WITH 
     t4 AS (SELECT n FROM (VALUES(0),(0),(0),(0)) t(n)) 
    , t256 AS (SELECT 0 AS n FROM t4 AS a CROSS JOIN t4 AS b CROSS JOIN t4 AS c CROSS JOIN t4 AS d) 
    , t16M AS (SELECT ROW_NUMBER() OVER (ORDER BY (a.n)) AS num FROM t256 AS a CROSS JOIN t256 AS b CROSS JOIN t256 AS c) 
INSERT INTO dbo.JobNormalized WITH (TABLOCKX) (JobID, HotJob, FeaturedJob, JobData) 
SELECT num, CASE num%10 WHEN 0 THEN 1 ELSE 0 END, CASE num%3 WHEN 0 THEN 1 ELSE 0 END, 'other data' 
FROM t16M 
WHERE num <= 25000; 

CREATE INDEX idx ON dbo.JobNormalized(HotJob, FeaturedJob) INCLUDE(JobData); 

DECLARE @HotJob int = 32; 
DECLARE @FeaturedJob int = 64; 

SELECT * 
FROM dbo.JobBitMask 
WHERE (JobType&@HotJob)[email protected] 
AND (JobType&@FeaturedJob)=0; 

SELECT * 
FROM dbo.JobNormalized 
WHERE HotJob = 1 
AND FeaturedJob = 0;