Pregunta de ajuste del índice

8

Estoy ajustando algunos índices y viendo algunos problemas me gustaría seguir su consejo

En 1 tabla hay 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- ¿Realmente necesito los primeros 2 índices, o debería eliminarlos?

2- hay consultas en ejecución que usan la condición donde profileid = xxxx y otras condiciones de uso donde profileid = xxxx e InstanceID = xxxxxx. ¿Por qué el optimizador elige el tercer índice, no el primero o el segundo?

También estoy ejecutando una consulta que obtiene la espera de bloqueo en cada índice. Si obtengo estos recuentos, ¿qué debo hacer para ajustar este í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.

la estructura de la mesa es

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 es un ejemplo (esta consulta creada por hibernate se ve extraña)

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

ingrese la descripción de la imagen aquí

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

ingrese la descripción de la imagen aquí

sebeid
fuente
Cualquier posibilidad de que pueda agregar cuál es la estructura de la tabla completa, cuál es la clave de agrupación y luego qué otras columnas se incluyen en las consultas que buscan profileid = xxxx y la consulta con profilerid = xxxx e instanciaid = xxxx. Hay mucho "depende" en estas respuestas y tener esa información definitivamente ayudaría a explicar de qué depende.
mskinner
Sería útil más información sobre los datos. Por ejemplo, si las estadísticas se han actualizado en la tabla, cuántos registros hay en la tabla junto con la unicidad, etc.
Glen Swan
@GlenSwan, hay 567644 registros en esta tabla. Las estadísticas se actualizan dos veces por semana. Martes y sábado
sebeid
2
Haga su propia investigación sobre comparaciones de características. Si bien existe cierta superposición, los Clústeres de conmutación por error y los Grupos de disponibilidad tienen diferentes características y cumplen con diferentes requisitos, por lo que no se puede preguntar genéricamente cuál es mejor. Debe comparar las características de cada uno con sus necesidades comerciales reales. Además, las preguntas sobre licencias / costos no son sobre el tema aquí. Por favor, lea esta meta publicación en su totalidad .
Aaron Bertrand

Respuestas:

6

Respuesta a la pregunta 1:

De lo que publicó, puede eliminar los dos primeros índices, ya que el tercero cubrirá todas las consultas que menciona y el optimizador de consultas también lo verá cuando construya el plan de consulta (en función del plan que publicó).

Respuesta a la pregunta 2:

Siempre usa el tercer índice porque ya tiene más datos en el índice con las dos teclas de índice adicionales ( InstanceId and AddressType). Esto evita que SQL necesite extraer InstanceId y AddressType de la clave primaria (la parte de búsqueda de claves del plan de ejecución) para satisfacer la consulta.

Lo que sugeriría es que elimine los dos primeros índices y reconstruya el tercero con columnas de inclusión para cubrir las otras columnas que se solicitan en la 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)

Esto debería ayudar con las consultas y debería eliminar la búsqueda de claves del plan de consulta.

Vea si los bloqueos se caen después de estos cambios y, si no lo hacen, podemos profundizar un poco más.

Aaron
fuente
Hice lo que me recomiendan y no hay más búsquedas de claves. estoy monitoreando bloqueos. Todavía necesito alguna aclaración para estos conteos. El bloqueo de fila espera: 484; duración total: 59 minutos; duración promedio: 7 segundos; El bloqueo de página espera: 5; duración total: 11 segundos; duración promedio: 2 segundos; Intentos de escalada de bloqueo: 36,949; Escalamientos reales: 0.
sebeid
@sebeid cuando se realizan inserciones / actualizaciones / eliminaciones en la tabla de direcciones, ¿se están modificando también otras tablas por la misma solicitud de lote? Si es así, ¿el lote comienza explícitamente una transacción para todas las declaraciones de modificación en el lote y solo se confirma o revierte al final del lote?
Aaron
No sé, ¿de dónde puedo obtener esta información? Gracias
sebeid
2
@sebeid si todo es una declaración generada desde hibernate, les preguntaría a sus desarrolladores, ya que ese podría ser el enfoque más simple, de lo contrario, tendrá que rastrear o configurar un evento extendido para tratar de atrapar las llamadas para que pueda ver lo que sucede. La declaración del lote. Ejemplo de perfil de eventos extendidos
Aaron
3

No es la pregunta indicada, pero puede obtener mejores planes de consulta con mejores consultas.
Está eliminando el exterior izquierdo con el lugar
donde profiledmo1_.Id=@P0 lo convierte en una unión

En índices solo los dos primeros

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

todo lo que se une es asegurarse de que esté en el Perfil, pero no está informando nada del perfil
y ¿cómo es que no?

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

Parece que podría eliminar los índices 1 y 2, ya que el índice 3 incluye toda la información (columnas) que necesita. Es posible que otro índice tenga sentido como un índice agrupado para representar la clave primaria.

Con esta información limitada, solo podemos adivinar. Si necesita más sugerencias, publique información más detallada como su estructura de tabla completa (tablas, índice, claves, ...), sus consultas y el plan de ejecución.

Josh Alvo
fuente
1
O un índice agrupado que no representa la clave primaria. Si bien estas dos cosas a menudo están estrechamente asociadas entre sí, y aunque se crea una clave principal como agrupada de forma predeterminada, no son (y no tienen que ser) la misma cosa.
Aaron Bertrand
Eso es cierto, por supuesto. :-)
Josh Alvo