/ / SQL Server 2016 - Bitwise vs декілька бітних стовпчиків - sql-сервер, bitwise-оператори

SQL Server 2016 - Bitwise vs декілька бітних стовпчиків - sql-сервер, bitwise-оператори

Я працюю з базою даних SQL Server, яка в даний час використовує ціле поле для класифікації завдань за допомогою побітових операторів.

Я припустив, що це буде вузьким місцем виконання,так почали досліджувати розділення цього стовпця на кілька індексованих бітних стовпчиків. Однак, після виконання деяких тестів, я помітив деякі незвичайні результати. Бітове запити перевершують бітові стовпці.

Це мої два запитання, які я тестую ...

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%.

Таблиця відносно невелика, лише 25 тис. Рядків.

Чи може хто-небудь запропонувати, чому це буде так?

Я не маю проблем зі збереженням бітового стовпця, але було просто цікаво, чому саме він виконує краще, коли все, що я читаю, здається, пропонує, що окремі стовпці повинні працювати краще.

Відповіді:

0 для відповіді № 1

Накладні витрати на доступ до кількох стовпцівсхоже, більше, ніж в одному стовпчику. Однак за допомогою нормованих стовпчиків можна створювати індекси, які можуть бути корисними, уникаючи повного сканування. Відносні витрати (які я беру з зерном солі) становлять 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;