/ / SQL Server 2016 - Bitové vs viac bitových stĺpcov - sql-server, bitové operátory

SQL Server 2016 - Bitové vs viac bitových stĺpcov - sql-server, bitové operátory

Pracujem s databázou SQL Server, ktorá v súčasnosti používa celé pole na kategorizáciu úloh pomocou bitových operátorov.

Predpokladal som, že to bude prekážkou v oblasti výkonnosti,začalo sa skúmať rozdelenie tohto stĺpca na viac stĺpcov indexovaných bitov. Po vykonaní niektorých testov som si však všimol niektoré nezvyčajné výsledky. Bitové dopyty prevyšujú bitové stĺpce.

Toto sú moje dve otázky, ktoré skúšam ...

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;

Analyzátor dopytu hlási, že relatívne náklady sú od 28% do 72%.

Tabuľka je relatívne malá, iba 25K riadkov.

Môže niekto navrhnúť, prečo by to tak bolo?

Nemám problém udržať bitový stĺp, ale bol len zvedavý, prečo presne to funguje lepšie, keď všetko, čo som čítal, zdá sa, že naznačuje, že samostatné stĺpce by mali fungovať lepšie.

odpovede:

0 pre odpoveď č. 1

Náklady na prístup k viacerým stĺpkamZdá sa, že je väčšia ako v jednom stĺpci. Avšak s normalizovanými stĺpcami môžete vytvoriť indexy, ktoré môžu byť užitočné, aby sa zabránilo úplnému skenovaniu. Relatívne náklady (ktoré beriem so zrnom soli) sú 91% a 9% s príkladom krycieho indexu nižšie. Možno budete musieť experimentovať, pretože optimálne indexovanie sa bude líšiť v závislosti od vašich dopytov a údajov.

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;