web-dev-qa-db-fra.com

Démarrage Varbinary StartSwith Utilisation de l'index

J'ai cette clé de type arbre (Think Object Oids - il est très similaire) de stocker et d'indexer dans une table, pour laquelle les requêtes veulent sélectionner leurs sous-arbres. Le moyen le plus simple de le faire sur un BTRee est d'utiliser le chemin d'arborescence comme une seule clé et descendez la clé avec une opération de démarrage pour trouver les blocs de lignes.

La représentation évidente est donc VARBINARY(n) *. Je ne peux pas penser à un moyen d'exprimer le démarrage d'une manière que SQL Server peut comprendre l'index de celui-ci.

Le plus évident consiste à emballer les données dans certaines VARCHAR avec une assemblée binaire et utilisez une opération like; Cependant j'ai découvert que like @n + '%' n'utilisera jamais d'index, mais seulement like 'literal%. Ajouter le WITH INDEX L'indice scanne toujours l'index dans son intégralité car SQL Server ne comprend tout simplement pas. Je ne veux vraiment pas penser à la façon d'échapper aux arguments en SQL afin que je puisse construire un EXEC. C'est juste la folie et une catastrophe de sécurité en attente de se produire.

Exprimant cela dans des tables récursives ordinaires et une interrogation avec SQL récursif est hors de question. La requête récursive sera alimentée par le serveur de base de données.

En fait, j'ai les données dans une longue chaîne de variables long en ce moment et peuvent sélectionner mon formulaire de sérialisation. Comme je l'ai dit, la forme naturelle est VARBINARY et cela ressemblerait vraiment à 0x000000100004A010000000D0000A000. La requête la plus commune est de la forme "donnez-moi tout en commençant par 0x000000100004A01 "ou dans le modèle naturel, les premières valeurs n de la chaîne de valeurs long. Je pourrais les écrire sous la forme a.b.c.d.e.f... Mais les chiffres individuels sont longs et viennent de cliquer sur des choses sur l'interface graphique.

À peu près parlant je cherche une forme plausible de

CREATE TABLE Record (
   RecordId BIGINT NOT NULL IDENTITY(1,1),
   RecordedDate DATETIME NOT NULL,
   RecordClass CHAR(1) NOT NULL,
   UserId INT NOT NULL,
   ObjectId VARBINARY(384) NOT NULL,
   RecordValue NVARCHAR(100) NULL,
   OwnerId BIGINT NULL, -- Joins to another table
   SubOwnerId BIGINT NULL, -- and yet another table
   PRIMARY KEY (RecordId)
)
CREATE INDEX name ON Record(RecordedDate);
CREATE INDEX name ON Record(OwnerId);
CREATE INDEX name ON Record(SubOwnerId);
CREATE INDEX name ON Record(ObjectId);

Quelle est la meilleure façon de faire un démarrage avec indice?

* J'ai calculé le plus grand possible N et c'est moins de 400

2
Joshua

Lorsque vous utilisez des variables locales SQL Server ne prend pas en compte leurs valeurs car elles sont inconnues pour le moment où elle génère un plan d'exécution pour la requête et crée un plan optimisé pour une valeur inconnue. C'est la raison pour laquelle il choisit de numériser. Vous pouvez utiliser une procédure SQL dynamique ou stockée pour créer SQL Server capable d'optimiser le plan d'exécution pour une valeur particulière. Par exemple:

DECLARE @LastName nvarchar(50)
DECLARE @sql nvarchar(4000);
SET @LastName = 'A%'
SET @sql = '
SELECT *
FROM Person.Person
WHERE LastName LIKE @LastName';
EXEC sp_executesql @sql, N'@LastName nvarchar(50)', @LastName
1
NikitaSerbskiy