Großer Leistungsunterschied bei Verwendung von group by vs different

80

Ich führe einige Tests auf einem HSQLDBServer 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 DISTINCTAbfrage 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 FORaber 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 HSQLDBmit allen unterschiedlichen Geschäftsschlüsseln ist die Leistung von DISTINCTjetzt besser - 3 Sekunden, verglichen GROUP BYmit etwa 9 Sekunden.

MySQLFü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.

Martin Dimitrov
quelle
2
Bitte zeigen Sie das Ergebnis von EXPLAIN PLANUND versuchen Sie, die DISTINCTAbfrage auszuführen GROUP BY, nachdem Sie die ausgeführt haben, um zu sehen, ob möglicherweise etwas Caching das Timing verzerrt ...
Yahia
Wenn Sie für jede Abfrage denselben Plan erhalten, klingt es so, als ob entweder die Tabellendaten oder das Ergebnis zwischengespeichert wurden.
Am
Ich habe sie so oft ausgeführt, dass Caching kein Problem ist. Ich poste die EXLAIN PLAN FORAusgabe.
Martin Dimitrov
Ich habe eine Idee, aber ich bin mir wirklich nicht sicher - bitte versuchen Sie es 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 dem GROUP BYWENN meine Idee richtig ist.
Yahia
@ Yahoo: immer noch sehr langsam - 94 Sekunden. Ich werde die gleichen Abfragen in MySQL ausführen, um zu sehen, was angezeigt wird
Martin Dimitrov

Antworten:

75

Die beiden Abfragen drücken dieselbe Frage aus. Anscheinend wählt der Abfrageoptimierer zwei verschiedene Ausführungspläne. Meine Vermutung wäre, dass der distinctAnsatz wie folgt ausgeführt wird:

  • Kopieren Sie alle business_keyWerte in eine temporäre Tabelle
  • Sortieren Sie die temporäre Tabelle
  • Scannen Sie die temporäre Tabelle und geben Sie jedes Element zurück, das sich von dem vorherigen unterscheidet

Das group bykönnte ausgeführt werden wie:

  • Scannen Sie die vollständige Tabelle und speichern Sie jeden Wert von business keyin einer Hashtabelle
  • Geben Sie die Schlüssel der Hashtabelle zurück

Die 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.

Andomar
quelle
Danke für die Antwort. Sind Ihre Vermutungen aus der EXPLAINAusgabe ersichtlich ? Beide sehen für mich gleich aus.
Martin Dimitrov
Soweit ich sehen kann, gibt der Plan nicht an, wie der Join ausgeführt wird. Ich bin mir nicht mal sicher, warum es einen Join ausführen würde. Es braucht wahrscheinlich einen HSQLDB-Spezialisten, um die EXPLAIN-Ausgabe zu lesen.
Andomar
Wie aus der Antwort hervorgeht, verwendet die zweite Methode mehr Speicher und trifft möglicherweise zu oft auf die Garbage Collection (GC). Wenn Sie die JVM-Speicherzuordnung erhöhen, sollte es keinen großen Unterschied zwischen den beiden Abfragezeiten geben.
Fredt
Ich habe einen zusätzlichen Test durchgeführt, indem ich alle unterschiedlichen Schlüssel in die Tabelle eingegeben habe (siehe oben). Glaubst du, das Ergebnis beweist deinen Standpunkt? Danke vielmals.
Martin Dimitrov
2
Kann ein KMU- Experten dies mit Beispielen in mehr Details bitte erklären ... Ich habe ein oft dieses Problem hatte , aber offenbar nicht um es zu bekommen um ... ich das Update wissen , aber ich möchte wissen , wie und warum
singhswat