Estoy realizando algunas pruebas en un HSQLDB
servidor 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 DISTINCT
consulta:
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 FOR
pero 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 HSQLDB
con todas las claves comerciales distintas, el rendimiento de DISTINCT
ahora es mejor: 3 segundos, en comparación con lo GROUP BY
que tomó alrededor de 9 segundos.
En MySQL
ambas 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 PLAN
Y intente ejecutar laDISTINCT
consulta DESPUÉS de ejecutar elGROUP BY
para ver si quizás algo de almacenamiento en caché está sesgando el tiempo ...EXLAIN PLAN FOR
salida.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 BY
SI 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
distinct
enfoque se ejecuta como:business_key
valores a una tabla temporalEl
group by
podría ejecutarse como:business key
en 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
EXPLAIN
resultado? Ambos me parecen iguales.