¿La secuencia de condiciones de juicio en SQL provocará una falla en el índice?

Vi una pregunta básica en el grupo sobre el uso de índices.

La pregunta está aquí, algunos amigos dicen que eligen B, algunos eligen C, algunos dicen que la pregunta no es rigurosa y algunos dicen que no hay respuesta, lo cual está mal.

Después de una larga discusión, hay dos problemas comunes que vale la pena mencionar:

  • a = 1 y b = 1 y b = 1 y a = 1 utilizarán efectivamente idx (b, a)?

  • b = 1 ¿Se seguirá utilizando el índice idx (a, b)?

El conocimiento real surge de la práctica, así que trato de operarlo en la computadora.

create database factory ;

use factory 
go 

create table dbo.workflow ( flowid int, flowamount int, flowcount int )

go 

Responda la primera pregunta primero, ¿ afectará el orden de las condiciones de juicio el uso del índice?

这儿模拟题目中的 idx(b,a) 索引结构

create index idx_amt_id on dbo.workflow(flowamount,flowid)

模拟 a=1 and b=1 的查询

select * from dbo.workflow 
where flowid = 1 and flowamount = 1 

模拟 b=1 and a=1 的查询

select * from dbo.workflow 
where flowamount = 1 and flowid = 1 

Se puede ver que cuando la tabla se crea nuevamente y no hay datos, el optimizador no juzgará si usar un índice en absoluto, sino que escaneará directamente toda la tabla. De todos modos, solo una página de datos.

Cuando agregamos algunos datos, observe la reacción:

Debo mencionar el uso de la tabla de conteo nuevamente. Realmente no puedo soportar el método de usar bucles para generar datos de prueba.

DECLARE @BEGIN DATETIME = '2010-01-01'

                ,@END DATETIME = '2017-10-30'

DECLARE @INC INT ;

SELECT @INC = DATEDIFF(DAY,@BEGIN,@END)



; WITH 

    L0 AS ( 

            SELECT * FROM (VALUES(1),(2),(3)) AS T(C) )

,    L1 AS (

            SELECT a.C,b.C AS BC FROM L0 AS a cross join L0 AS b )

,    L2 AS (

            SELECT a.C,b.C AS BC FROM L1 AS a cross join L1 AS b )

,    L3 AS (

            SELECT a.C,b.C AS BC FROM L2 AS a cross join L2 AS b )

,    L4 AS (

            SELECT a.C,b.C AS BC FROM L3 AS a cross join L3 AS b )

,    L5 AS (

            SELECT a.C,b.C AS BC FROM L4 AS a cross join L4 AS b )

insert into  dbo.workflow (flowid,flowamount,flowcount)            

SELECT TOP 50000 RNK , RNK * 10, RNK + 20 

FROM 

(

SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS RNK 

FROM L5

) M 

En este momento, hay 50,000 piezas de datos en la tabla y luego mire el plan de ejecución de las dos consultas anteriores:

这儿模拟题目中的 idx(b,a) 索引结构

create index idx_amt_id on dbo.workflow(flowamount,flowid)

模拟 a=1 and b=1 的查询

select * from dbo.workflow 
where flowid = 1 and flowamount = 1 

模拟 b=1 and a=1 的查询

select * from dbo.workflow 
where flowamount = 1 and flowid = 1 

Obviamente, seguiremos el modelo index idx (b, a), que no tiene nada que ver con b first y a first. El optimizador puede optimizar la reorganización de esta parte de la expresión.

Sin embargo, ¿no hay requisitos de orden para todas las expresiones condicionales ? seguramente no

Solo cuando se juzga la condición de igualdad, el orden no es importante. Una vez que se usa una expresión para juicio no igual, el orden es muy importante, como sigue:

select * from dbo.workflow 
where flowamount > 39 and flowid = 1 


select * from dbo.workflow 
where flowid = 1 and flowamount > 39  

Aquí, el optimizador solicita (la parte en fuente verde) que cree un índice para condiciones de juicio iguales primero, y un índice para campos de juicio no iguales (flowid, flowamount) detrás. Entonces, en esencia, la secuencia de campos en la estructura del índice no está restringida por el orden de los campos de expresión de condición de juicio de igualdad en la consulta, sino por la expresión de juicio de desigualdad. Es decir, el campo de juicio no igual (cantidad de flujo> 39) debe colocarse después del campo de juicio igual (flowid = 1).

create index idx_id_amtr on dbo.workflow(flowid,flowamount)


select * from dbo.workflow 
where flowamount > 39 and flowid = 1 


select * from dbo.workflow 
where flowid = 1 and flowamount > 39  

Mira los dos planes de ejecución:

Aquí está el índice idx_id_amtr que acabamos de crear

La segunda pregunta, ¿ b = 1 seguirá usando el índice idx (a, b) ?

En el ejemplo anterior, se establece el índice de índice (flowamount, flowid), entonces el problema a resolver corresponde al índice de índice (flowamount, flowid) donde flowid = 1?

select * from dbo.workflow 
where  flowid = 1 

Se puede ver que b = 1 no usará el índice idx (a, b).

Tenga en cuenta que otras bases de datos como Oracle, mysql, pg, etc. pueden ser diferentes. Pueden probar la operación real y discutirla juntos. Los algoritmos de los respectivos optimizadores son diferentes y la optimización es un poco sorprendente. No te enredes demasiado.

Supongo que te gusta

Origin blog.csdn.net/weixin_45784983/article/details/108143484
Recomendado
Clasificación