Pergunta de ajuste do índice

8

Estou ajustando alguns índices e vendo alguns problemas que gostaria de seguir seu conselho

Em uma tabela existem 3 índices

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- Preciso mesmo dos 2 primeiros índices ou devo descartá-los?

2- existem consultas em execução que usam a condição em que profileid = xxxx e outras usam em que profileid = xxxx e InstanceID = xxxxxx. Por que o otimizador escolhe o terceiro índice e não o 1º ou o 2º?

Também estou executando uma consulta que recebe a espera de bloqueio em cada índice. Se estou recebendo essas contagens, o que devo fazer para ajustar esse índice?

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.

estrutura da tabela é

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
 )

este é um exemplo (essa consulta criada pelo hibernate parece estranha)

(@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 

insira a descrição da imagem aqui

(@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

insira a descrição da imagem aqui

sebeid
fonte
Qualquer chance de adicionar a estrutura completa da tabela, qual é a chave de cluster e quais outras colunas estão sendo incluídas nas consultas que procuram profileid = xxxx e na consulta com profilerid = xxxx e instanceid = xxxx. Há muito "depende" nessas respostas e ter essas informações definitivamente ajudaria a explicar do que depende.
mskinner
Mais informações sobre os dados seriam úteis. Por exemplo, se as estatísticas foram atualizadas na tabela, quantos registros existem na tabela, juntamente com a exclusividade e assim por diante.
Glen Swan
@GlenSwan, existem 567644 registros nesta tabela. As estatísticas são atualizadas duas vezes por semana. Terça e sábado
sebeid 20/08/2015
2
Faça sua própria pesquisa sobre comparações de recursos. Embora exista alguma sobreposição, os Clusters de Failover e os Grupos de Disponibilidade têm recursos diferentes e atendem a requisitos diferentes; portanto, você não pode realmente perguntar genericamente qual é o melhor. Você precisa comparar os recursos de cada um com suas necessidades comerciais reais. Além disso, as questões de licenciamento / custo não são abordadas aqui. Por favor, leia esta meta post na íntegra .
Aaron Bertrand

Respostas:

6

Resposta à pergunta 1:

Pelo que você postou, você pode descartar os dois primeiros índices, pois o terceiro cobrirá todas as consultas mencionadas e o otimizador de consultas também o vê quando cria o plano de consulta (com base no plano que você postou).

Resposta à pergunta 2:

Ele está sempre usando o terceiro índice, porque já tem mais dados no índice com as duas chaves de índice adicionais ( InstanceId and AddressType). Isso evita que o SQL precise extrair InstanceId e AddressType da chave primária (a parte de pesquisa de chave do plano de execução) para satisfazer a consulta.

O que eu sugeriria é soltar os dois primeiros índices e reconstruir o terceiro com colunas de inclusão para cobrir as outras colunas que estão sendo solicitadas na consulta

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)

Isso deve ajudar nas consultas e remover a pesquisa de chave do plano de consulta.

Veja se os bloqueios caem após essas alterações e se não o fizermos, podemos nos aprofundar um pouco mais.

Aaron
fonte
Eu fiz o que você recomenda e não há mais pesquisa de chave. estou monitorando bloqueios .. ainda preciso de alguns esclarecimentos para essas contagens O bloqueio de linha aguarda: 484; duração total: 59 minutos; duração média: 7 segundos; O bloqueio de página aguarda: 5; duração total: 11 segundos; duração média: 2 segundos; Tentativas de escalação de bloqueio: 36.949; Escalações reais: 0.
sebeid
@ quando as inserções / atualizações / exclusões são feitas na tabela Endereço, outras tabelas também estão sendo modificadas pela mesma solicitação em lote? Em caso afirmativo, o lote inicia explicitamente uma transação para todas as instruções de modificação do lote e somente confirma ou retrocede no final do lote?
Aaron
Não sei, de onde posso obter essas informações. Obrigado
sebeid
2
@sebeid se tudo é uma declaração gerada a partir do hibernate, eu perguntaria aos desenvolvedores como essa pode ser a abordagem mais simples; caso contrário, você precisará rastrear ou configurar um evento estendido para tentar interceptar as chamadas, para que você possa ver o que está acontecendo em a instrução de lote. Exemplo de perfil de eventos estendidos
Aaron
3

Não é a pergunta declarada, mas pode obter melhores planos de consulta com melhores consultas
Você está matando a parte externa esquerda com o local
onde profiledmo1_.Id=@P0 transforma isso em uma junção

Nos índices, apenas os dois primeiros

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

tudo o que a associação faz é garantir que ele esteja no perfil, mas você não está relatando nada do perfil
e como isso não acontece?

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

Parece que você pode descartar o índice 1 e 2, pois o índice 3 inclui todas as informações (colunas) necessárias. Pode ser possível que outro índice faça sentido como índice clusterizado para representar a chave primária.

Com esta informação limitada, podemos apenas adivinhar. Se você precisar de mais dicas, publique informações mais detalhadas como sua estrutura de tabela completa (tabelas, índice, chaves, ...), suas consultas e o plano de execução.

Josh Alvo
fonte
11
Ou um índice clusterizado que não representa a chave primária. Embora essas duas coisas geralmente estejam fortemente associadas uma à outra, e enquanto uma chave primária é criada como agrupada por padrão, elas não são (e não precisam ser) a mesma coisa.
Aaron Bertrand
Isso é verdade, é claro. :-)
Josh Alvo