Ich führe einige Tests auf einem HSQLDB
Server mit einer Tabelle mit 500 000 Einträgen durch. Die Tabelle hat keine Indizes. Es gibt 5000 verschiedene Geschäftsschlüssel. Ich brauche eine Liste von ihnen. Natürlich habe ich mit einer DISTINCT
Abfrage begonnen:
SELECT DISTINCT business_key FROM memory WHERE
concept <> 'case' or
attrib <> 'status' or
value <> 'closed'
Es dauert ungefähr 90 Sekunden !!!
Dann habe ich versucht GROUP BY
:
SELECT business_key FROM memory WHERE
concept <> 'case' or
attrib <> 'status' or
value <> 'closed'
GROUP BY business_key
Und es dauert 1 Sekunde !!!
Ich habe versucht, den Unterschied herauszufinden, den ich ausgeführt habe, EXLAIN PLAN FOR
aber es scheint für beide Abfragen die gleichen Informationen zu geben.
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
EDIT : Ich habe zusätzliche Tests gemacht. Mit 500 000 Datensätzen HSQLDB
mit allen unterschiedlichen Geschäftsschlüsseln ist die Leistung von DISTINCT
jetzt besser - 3 Sekunden, verglichen GROUP BY
mit etwa 9 Sekunden.
MySQL
Führen Sie in beiden Abfragen dasselbe aus:
MySQL: 500.000 Zeilen - 5.000 verschiedene Geschäftsschlüssel: Beide Abfragen: 0,5 Sekunden MySQL: 500.000 Zeilen - alle verschiedenen Geschäftsschlüssel:
SELECT DISTINCT ...
- 11 Sekunden
SELECT ... GROUP BY business_key
- 13 Sekunden
Das Problem hängt also nur mit zusammen HSQLDB
.
Ich wäre sehr dankbar, wenn jemand erklären könnte, warum es so einen drastischen Unterschied gibt.
EXPLAIN PLAN
UND versuchen Sie, dieDISTINCT
Abfrage auszuführenGROUP BY
, nachdem Sie die ausgeführt haben, um zu sehen, ob möglicherweise etwas Caching das Timing verzerrt ...EXLAIN PLAN FOR
Ausgabe.SELECT DISTINCT business_key FROM (SELECT business_key FROM memory WHERE concept <> 'case' or attrib <> 'status' or value <> 'closed')
- dies sollte die gleiche Leistung zeigen, die Sie mit demGROUP BY
WENN meine Idee richtig ist.Antworten:
Die beiden Abfragen drücken dieselbe Frage aus. Anscheinend wählt der Abfrageoptimierer zwei verschiedene Ausführungspläne. Meine Vermutung wäre, dass der
distinct
Ansatz wie folgt ausgeführt wird:business_key
Werte in eine temporäre TabelleDas
group by
könnte ausgeführt werden wie:business key
in einer HashtabelleDie erste Methode ist für die Speichernutzung optimiert: Sie würde immer noch eine recht gute Leistung erbringen, wenn ein Teil der temporären Tabelle ausgetauscht werden muss. Die zweite Methode optimiert die Geschwindigkeit, erfordert jedoch möglicherweise viel Speicher, wenn viele verschiedene Schlüssel vorhanden sind.
Da Sie entweder über genügend Speicher oder wenige verschiedene Schlüssel verfügen, übertrifft die zweite Methode die erste. Es ist nicht ungewöhnlich, dass zwischen zwei Ausführungsplänen Leistungsunterschiede von 10x oder sogar 100x auftreten.
quelle
EXPLAIN
Ausgabe ersichtlich ? Beide sehen für mich gleich aus.