Estoy realizando algunas pruebas en un HSQLDBservidor con una tabla que contiene 500 000 entradas. La tabla no tiene índices. Hay 5000 claves comerciales distintas. Necesito una lista de ellos. Naturalmente comencé con una DISTINCTconsulta:
SELECT DISTINCT business_key FROM memory WHERE
concept <> 'case' or
attrib <> 'status' or
value <> 'closed'
¡¡¡Tarda unos 90 segundos !!!
Luego intenté usar GROUP BY:
SELECT business_key FROM memory WHERE
concept <> 'case' or
attrib <> 'status' or
value <> 'closed'
GROUP BY business_key
¡¡¡Y tarda 1 segundo !!!
Intenté averiguar la diferencia que ejecuté, EXLAIN PLAN FORpero parece dar la misma información para ambas consultas.
EXLAIN PLAN FOR DISTINCT ...
isAggregated=[false]
columns=[
COLUMN: PUBLIC.MEMORY.BUSINESS_KEY
]
[range variable 1
join type=INNER
table=MEMORY
alias=M
access=FULL SCAN
condition = [ index=SYS_IDX_SYS_PK_10057_10058
other condition=[
OR arg_left=[
OR arg_left=[
NOT_EQUAL arg_left=[
COLUMN: PUBLIC.MEMORY.CONCEPT] arg_right=[
VALUE = case, TYPE = CHARACTER]] arg_right=[
NOT_EQUAL arg_left=[
COLUMN: PUBLIC.MEMORY.ATTRIB] arg_right=[
VALUE = status, TYPE = CHARACTER]]] arg_right=[
NOT_EQUAL arg_left=[
COLUMN: PUBLIC.MEMORY.VALUE] arg_right=[
VALUE = closed, TYPE = CHARACTER]]]
]
]]
PARAMETERS=[]
SUBQUERIES[]
Object References
PUBLIC.MEMORY
PUBLIC.MEMORY.CONCEPT
PUBLIC.MEMORY.ATTRIB
PUBLIC.MEMORY.VALUE
PUBLIC.MEMORY.BUSINESS_KEY
Read Locks
PUBLIC.MEMORY
WriteLocks
EXLAIN PLAN FOR SELECT ... GROUP BY ...
isDistinctSelect=[false]
isGrouped=[true]
isAggregated=[false]
columns=[
COLUMN: PUBLIC.MEMORY.BUSINESS_KEY
]
[range variable 1
join type=INNER
table=MEMORY
alias=M
access=FULL SCAN
condition = [ index=SYS_IDX_SYS_PK_10057_10058
other condition=[
OR arg_left=[
OR arg_left=[
NOT_EQUAL arg_left=[
COLUMN: PUBLIC.MEMORY.CONCEPT] arg_right=[
VALUE = case, TYPE = CHARACTER]] arg_right=[
NOT_EQUAL arg_left=[
COLUMN: PUBLIC.MEMORY.ATTRIB] arg_right=[
VALUE = status, TYPE = CHARACTER]]] arg_right=[
NOT_EQUAL arg_left=[
COLUMN: PUBLIC.MEMORY.VALUE] arg_right=[
VALUE = closed, TYPE = CHARACTER]]]
]
]]
groupColumns=[
COLUMN: PUBLIC.MEMORY.BUSINESS_KEY]
PARAMETERS=[]
SUBQUERIES[]
Object References
PUBLIC.MEMORY
PUBLIC.MEMORY.CONCEPT
PUBLIC.MEMORY.ATTRIB
PUBLIC.MEMORY.VALUE
PUBLIC.MEMORY.BUSINESS_KEY
Read Locks
PUBLIC.MEMORY
WriteLocks
EDITAR : Hice pruebas adicionales. Con 500 000 registros HSQLDBcon todas las claves comerciales distintas, el rendimiento de DISTINCTahora es mejor: 3 segundos, en comparación con lo GROUP BYque tomó alrededor de 9 segundos.
En MySQLambas consultas se realiza lo mismo:
MySQL: 500 000 filas - 5 000 claves comerciales distintas: ambas consultas: 0,5 segundos MySQL: 500 000 filas - todas las claves comerciales distintas:
SELECT DISTINCT ...- 11 segundos
SELECT ... GROUP BY business_key- 13 segundos
Entonces el problema solo está relacionado con HSQLDB.
Estaré muy agradecido si alguien me puede explicar por qué hay una diferencia tan drástica.

EXPLAIN PLANY intente ejecutar laDISTINCTconsulta DESPUÉS de ejecutar elGROUP BYpara ver si quizás algo de almacenamiento en caché está sesgando el tiempo ...EXLAIN PLAN FORsalida.SELECT DISTINCT business_key FROM (SELECT business_key FROM memory WHERE concept <> 'case' or attrib <> 'status' or value <> 'closed'), esto debería mostrar el mismo rendimiento que ve con elGROUP BYSI mi idea es correcta.Respuestas:
Las dos consultas expresan la misma pregunta. Aparentemente, el optimizador de consultas elige dos planes de ejecución diferentes. Mi conjetura sería que el
distinctenfoque se ejecuta como:business_keyvalores a una tabla temporalEl
group bypodría ejecutarse como:business keyen una tabla hashEl primer método se optimiza para el uso de la memoria: aún funcionaría razonablemente bien cuando parte de la tabla temporal debe intercambiarse. El segundo método optimiza la velocidad, pero potencialmente requiere una gran cantidad de memoria si hay muchas claves diferentes.
Dado que tiene suficiente memoria o pocas claves diferentes, el segundo método supera al primero. No es inusual ver diferencias de rendimiento de 10x o incluso 100x entre dos planes de ejecución.
fuente
EXPLAINresultado? Ambos me parecen iguales.