Mi aspetto che questi due SELECT
s abbiano lo stesso piano di esecuzione e le stesse prestazioni. Poiché è presente un carattere jolly iniziale su LIKE
, mi aspetto una scansione dell'indice. Quando eseguo questo e guardo i piani, il primo SELECT
si comporta come previsto (con una scansione). Ma il secondo piano SELECT
mostra un indice di ricerca, e viene eseguito 20 volte più veloce.Come può LIKE '% ...' cercare su un indice?
Codice:
-- Uses index scan, as expected:
SELECT 1
FROM AccountAction
WHERE AccountNumber LIKE '%441025586401'
-- Uses index seek somehow, and runs much faster:
declare @empty VARCHAR(30) = ''
SELECT 1
FROM AccountAction
WHERE AccountNumber LIKE '%441025586401' + @empty
Domanda:
Come SQL Server utilizza un indice di ricerca quando il pattern inizia con un carattere jolly?
Domanda bonus:
Perché concatenando un cambiamento stringa vuota/di migliorare il piano di esecuzione?
Dettagli:
- C'è un indice non cluster su
Accounts.AccountNumber
- Ci sono altri indici, ma sia la cercano e la scansione sono questo indice.
- La colonna
Accounts.AccountNumber
è un nullablevarchar(30)
- Il server è 2012
di tabelle e indici definizioni SQL Server:
CREATE TABLE [updatable].[AccountAction](
[ID] [int] IDENTITY(1,1) NOT NULL,
[AccountNumber] [varchar](30) NULL,
[Utility] [varchar](9) NOT NULL,
[SomeData1] [varchar](10) NOT NULL,
[SomeData2] [varchar](200) NULL,
[SomeData3] [money] NULL,
--...
[Created] [datetime] NULL,
CONSTRAINT [PK_Account] PRIMARY KEY NONCLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE NONCLUSTERED INDEX [IX_updatable_AccountAction_AccountNumber_UtilityCode_ActionTypeCd] ON [updatable].[AccountAction]
(
[AccountNumber] ASC,
[Utility] ASC
)
INCLUDE ([SomeData1], [SomeData2], [SomeData3]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
CREATE CLUSTERED INDEX [CIX_Account] ON [updatable].[AccountAction]
(
[Created] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
NOTA: Ecco l'attuale piano di di esecuzione per la due domande. I nomi degli oggetti differiscono leggermente dal codice sopra perché stavo cercando di mantenere la domanda semplice.
c'è differenza di esecuzione reale o solo nei piani di stima? –
@GordonLinoff Il numero di versione di SQL Server 2012 è 11, 2008 R2: 10.5, 2008: 10, ecc. – swasheck
Non so quanto possa essere importante, ma le query effettivamente eseguite erano 'LIKE '% 441025586401%'' , con un carattere jolly all'inizio e alla fine – Lamak