Question de réglage d'index

8

Je suis en train de régler certains index et je vois que certains problèmes voudraient prendre votre avis

Sur 1 table il y a 3 index

dbo.Address.IX_Address_ProfileId 
[1 KEY] ProfileId {int 4}
Reads: 0 Writes:10,519

dbo.Address.IX_Address 
[2 KEYS] ProfileId {int 4}, InstanceId {int 4}
Reads: 0 Writes:10,523

dbo.Address.IX_Address_profile_instance_addresstype
[3 KEYS] ProfileId {int 4}, InstanceId {int 4}, AddressType {int 4}
Reads: 149677 (53,247 seek) Writes:10,523

1- Ai-je vraiment besoin des 2 premiers index, ou dois-je les déposer?

2- il y a des requêtes en cours d'exécution qui utilisent une condition où profileid = xxxx et une autre condition d'utilisation où profileid = xxxx et InstanceID = xxxxxx. Pourquoi l'optimiseur choisit le 3e index et non le 1er ou le 2e?

J'exécute également une requête qui obtient l'attente de verrouillage sur chaque index. Si je reçois ces chiffres, que dois-je faire pour régler cet indice?

Row lock waits: 484; total duration: 59 minutes; avg duration: 7 seconds; 
Page lock waits: 5; total duration: 11 seconds; avg duration: 2 seconds; 
Lock escalation attempts: 36,949; Actual Escalations: 0.

la structure de la table est

TABLE [dbo].[Address](
[Id] [int] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,
[AddressType] [int] NULL,
[isPreferredAddress] [bit] NULL,
[StreetAddress1] [nvarchar](255) NULL,
[StreetAddress2] [nvarchar](255) NULL,
[City] [nvarchar](50) NULL,
[State_Id] [int] NOT NULL,
[Zip] [varchar](20) NULL,
[Country_Id] [int] NOT NULL,
[CurrentUntil] [date] NULL,
[CreatedDate] [datetime] NOT NULL,
[UpdatedDate] [datetime] NOT NULL,
[ProfileId] [int] NOT NULL,
[InstanceId] [int] NOT NULL,
[County_id] [int] NULL,
 CONSTRAINT [PK__Address__3214EC075E4BE276] PRIMARY KEY CLUSTERED 
(
   [Id] ASC
 )

ceci est un exemple (cette requête créée par hibernate semble donc étrange)

(@P0 bigint)select addresses0_.ProfileId as Profile15_109_1_
, addresses0_.Id as Id1_20_1_
, addresses0_.Id as Id1_20_0_
, addresses0_.AddressType as AddressT2_20_0_
, addresses0_.City as City3_20_0_
, addresses0_.Country_Id as Country_4_20_0_
, addresses0_.County_id as County_i5_20_0_
, addresses0_.CreatedDate as CreatedD6_20_0_
, addresses0_.CurrentUntil as CurrentU7_20_0_
, addresses0_.InstanceId as Instance8_20_0_
, addresses0_.isPreferredAddress as isPrefer9_20_0_
, addresses0_.ProfileId as Profile15_20_0_
, addresses0_.State_Id as State_I10_20_0_
, addresses0_.StreetAddress1 as StreetA11_20_0_
, addresses0_.StreetAddress2 as StreetA12_20_0_
, addresses0_.UpdatedDate as Updated13_20_0_
, addresses0_.Zip as Zip14_20_0_ 
from dbo.Address addresses0_ 
where addresses0_.ProfileId=@P0 

entrez la description de l'image ici

(@P0 bigint,@P1 bigint)
select addressdmo0_.Id as Id1_20_
, addressdmo0_.AddressType as AddressT2_20_
, addressdmo0_.City as City3_20_
, addressdmo0_.Country_Id as Country_4_20_
, addressdmo0_.County_id as County_i5_20_
, addressdmo0_.CreatedDate as CreatedD6_20_
, addressdmo0_.CurrentUntil as CurrentU7_20_
, addressdmo0_.InstanceId as Instance8_20_
, addressdmo0_.isPreferredAddress as isPrefer9_20_
, addressdmo0_.ProfileId as Profile15_20_
, addressdmo0_.State_Id as State_I10_20_
, addressdmo0_.StreetAddress1 as StreetA11_20_
, addressdmo0_.StreetAddress2 as StreetA12_20_
, addressdmo0_.UpdatedDate as Updated13_20_
, addressdmo0_.Zip as Zip14_20_ 
from dbo.Address addressdmo0_ 
left outer join dbo.Profile profiledmo1_ 
on addressdmo0_.ProfileId=profiledmo1_.Id 
where profiledmo1_.Id=@P0 and addressdmo0_.InstanceId=@P1

entrez la description de l'image ici

sebeid
la source
Toutes les chances que vous puissiez ajouter la structure complète de la table, la clé de clustering et les autres colonnes incluses dans les requêtes qui recherchent profileid = xxxx et la requête avec profilerid = xxxx et instanceid = xxxx. Il y a beaucoup de "ça dépend" dans ces réponses et avoir cette information aiderait certainement à expliquer de quoi cela dépend.
mskinner
Plus d'informations sur les données seraient utiles. Par exemple, si des statistiques ont été mises à jour sur la table, combien d'enregistrements sont dans la table avec l'unicité et ainsi de suite.
Glen Swan
@GlenSwan, il y a 567644 enregistrements dans ce tableau. Les statistiques sont mises à jour deux fois par semaine. Mardi et samedi
sebeid
2
Veuillez effectuer vos propres recherches sur les comparaisons de fonctionnalités. Bien qu'il y ait un certain chevauchement, les clusters de basculement et les groupes de disponibilité ont des fonctionnalités différentes et répondent à des exigences différentes, vous ne pouvez donc pas vraiment demander de manière générique laquelle est la meilleure. Vous devez comparer les fonctionnalités de chacun avec vos besoins commerciaux réels. De plus, les questions de licence / coût ne sont pas abordées ici. Veuillez lire ce méta post dans son intégralité .
Aaron Bertrand

Réponses:

6

Réponse à la question 1:

À partir de ce que vous avez publié, vous pouvez supprimer les deux premiers index, car le troisième couvrira toutes les requêtes que vous mentionnez et l'optimiseur de requêtes le verra également lors de la création du plan de requête (en fonction du plan que vous avez publié).

Réponse à la question 2:

Il utilise toujours le troisième index car il contient déjà plus de données dans l'index avec les deux clés d'index supplémentaires ( InstanceId and AddressType). Cela empêche SQL d'avoir à extraire InstanceId et AddressType de la clé primaire (la partie de recherche de clé du plan d'exécution) pour satisfaire la requête.

Je suggérerais de supprimer les deux premiers index et de reconstruire le troisième avec des colonnes d'inclusion pour couvrir les autres colonnes demandées dans la requête

Create index IX_Address_profile_instance_addresstype 
on dbo.address  (ProfileId, InstanceId, AddressType) 
include(<put in the remaining columns comma delimited>) 
with (drop_existing=on,sort_in_tempdb=on)

Cela devrait aider avec les requêtes et supprimer la recherche de clé du plan de requête.

Voyez si les verrous tombent après ces changements et s'ils ne le font pas, nous pouvons creuser un peu plus profondément.

Aaron
la source
j'ai fait ce que vous recommandez et il n'y a plus de recherche de clé. je surveille les verrous .. j'ai encore besoin de précisions pour ces chiffres Attente des verrous de ligne: 484; durée totale: 59 minutes; durée moyenne: 7 secondes; Attente du verrouillage de la page: 5; durée totale: 11 secondes; durée moyenne: 2 secondes; Tentatives d'escalade de verrouillage: 36 949;
Escalades
@sebeid lorsque des insertions / mises à jour / suppressions sont effectuées sur la table d'adresses, d'autres tables sont-elles également modifiées par la même demande de lot? Dans l'affirmative, le lot commence-t-il explicitement une transaction pour toutes les instructions de modification dans le lot et ne valide ou annule qu'à la fin du lot?
Aaron
je ne sais pas, d'où puis-je obtenir ces informations. Merci
sebeid
2
@sebeid si tout est une instruction générée depuis hibernate, je demanderais à vos développeurs car cela pourrait être l'approche la plus simple, sinon vous devrez suivre ou configurer un événement étendu pour essayer de piéger les appels afin que vous puissiez voir ce qui se passe dans l'instruction batch. Exemple de profileur d' événements étendus
Aaron
3

Pas la question indiquée, mais peut obtenir de meilleurs plans de requête avec de meilleures requêtes
Vous tuez l'extérieur gauche avec l'endroit
où profiledmo1_.Id=@P0 transforme cela en jointure

Sur les index uniquement les deux premiers

select addressdmo0_.Id as Id1_20_
     , ...
     , addressdmo0_.Zip as Zip14_20_ 
  from dbo.Address addressdmo0_ 
  join dbo.Profile profiledmo1_ 
    on addressdmo0_.ProfileId = profiledmo1_.Id 
   and profiledmo1_.Id = @P0 
   and addressdmo0_.InstanceId = @P1

tout ce que la jointure fait est de s'assurer qu'elle se trouve dans le profil, mais vous ne signalez rien du profil
et comment n'est-ce pas?

select addressdmo0_.Id as Id1_20_
     , ...
     , addressdmo0_.Zip as Zip14_20_ 
  from dbo.Address addressdmo0_ 
 where addressdmo0_.ProfileId  = @P0 
   and addressdmo0_.InstanceId = @P1
paparazzo
la source
2

Il semble que vous puissiez supprimer les index 1 et 2, car l'index 3 comprend toutes les informations (colonnes) dont vous avez besoin. Il est possible qu'un autre index ait un sens en tant qu'index cluster pour représenter la clé primaire.

Avec ces informations limitées, nous pouvons simplement deviner. Si vous avez besoin de plus de conseils, veuillez publier des informations plus détaillées comme la structure complète de votre table (tables, index, clés, ...), vos requêtes et le plan d'exécution.

Josh Alvo
la source
1
Ou un index cluster qui ne représente pas la clé primaire. Bien que ces deux choses soient souvent étroitement associées, et bien qu'une clé primaire soit créée en cluster par défaut, elles ne sont pas (et ne doivent pas être) la même chose.
Aaron Bertrand
C'est vrai bien sûr. :-)
Josh Alvo