/ / SQL Server 2016 - ビットワイズ対複数ビットの列 - sql-server、ビットワイズ演算子

SQL Server 2016 - ビットワイズ対複数ビットの列 - SQL Server、ビットワイズ演算子

私はビットフィールド演算子を使ってジョブを分類するために現在整数フィールドを使っているSQL Serverデータベースを使って作業しています。

私はこれがパフォーマンスのボトルネックになると想定していましたが、この列を複数のインデックス付きビット列に分割することを検討し始めました。しかし、いくつかのテストを行った後、私はいくつかの珍しい結果に気付きました。ビットごとのクエリはビット列より優れています。

これらは私がテストしている2つの質問です...

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

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

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

クエリアナライザは、相対コストが28〜72%であることを報告します。

テーブルは比較的小さく、わずか25K行です。

なぜこれが事実だろうと誰かが示唆することができますか?

私はビット単位の列を維持することには問題ありませんが、なぜ私が読んだことが別々の列がうまくいくかを示唆しているように見えるときに、それがより正確に実行される理由が不思議でした。

回答:

回答№1は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)=@HotJob
AND (JobType&@FeaturedJob)=0;

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