/ / SQL Server 2016 - Colonnes binaires vs multiples bits - Serveur SQL, Opérateurs binaires

SQL Server 2016 - Colonnes bit à bit et colonnes à plusieurs bits - sql-server, opérateurs binaires

Je travaille avec une base de données SQL Server qui utilise actuellement un champ entier pour classer les travaux à l’aide d’opérateurs au niveau du bit.

J'ai supposé que ce serait un goulot d'étranglement,alors commencé à étudier la division de cette colonne en plusieurs colonnes de bits indexées. Cependant, après quelques tests, j’ai remarqué quelques résultats inhabituels. Les requêtes au niveau du bit dépassent les colonnes de bits.

Ce sont mes deux requêtes que je teste ...

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;

L'analyseur de requête indique que les coûts relatifs sont compris entre 28% et 72%.

La table est relativement petite, seulement 25 000 lignes.

Quelqu'un peut-il suggérer pourquoi cela serait le cas?

Je n’ai aucun problème à conserver la colonne au niveau du bit, mais j’étais curieux de savoir pourquoi elle fonctionne mieux, alors que tout ce que j'ai lu semble suggérer que des colonnes séparées fonctionnent mieux.

Réponses:

0 pour la réponse № 1

La surcharge d'accès aux multiples colonnessemble être plus grand que celui d'une seule colonne. Cependant, avec les colonnes normalisées, vous pouvez créer des index pouvant être utiles, en évitant une analyse complète. Les coûts relatifs (que je prends avec un grain de sel) sont de 91% et 9% avec l'exemple de couverture ci-dessous. Vous devrez peut-être expérimenter, car l'indexation optimale variera en fonction de vos requêtes et de vos données.

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;