Ich habe ein sehr seltsames Verhalten von MySQL realisiert, für das ich keine Erklärung habe.MySQL Performance - String vs Integer
Dies ist eine nicht allzu komplexe Abfrage:
SELECT
COUNT(*)
FROM
incidents.incidents AS inc,
incidents.enrichment AS enr
WHERE
inc.Id <= 606734
AND inc.Id >= 1
AND inc.Id = enr.ParentTableId
AND (
enr.Enricher3State = 2
OR enr.Enricher4State = 2
OR enr.Enricher5State = 2
OR enr.Enricher9State = 2
);
Die Säulen Enricher3State, Enricher4State, Enricher5State, Enricher9State einen Index zu tun haben und sind von dem Datentyp int (11).
Jetzt habe ich versucht, diesen enricher [x] Staat in einen String zu ändern:
SELECT
COUNT(*)
FROM
incidents.incidents AS inc,
incidents.enrichment AS enr
WHERE
inc.Id <= 606734
AND inc.Id >= 1
AND inc.Id = enr.ParentTableId
AND (
enr.Enricher3State = '2'
OR enr.Enricher4State = '2'
OR enr.Enricher5State = '2'
OR enr.Enricher9State = '2'
);
Jeder gesunder Menschenverstand würde sagen, dass die String-Variante die gleichen durchführen soll, oder langsamer, da der Datentyp der Spalte ist Ganzzahl!
Aber anscheinend ist das nicht der Fall!
Abfrage mit Integer-Notation (erster): 7.23048825s
Abfrage mit String-Notation (letzten): 5.22188450s
Wie Sie sehen können, gibt es einen riesigen Unterschied in der Leistung, auch wenn die Abfrage Die Kosten sind in beiden Fällen gleich.
Ich habe absolut keine Ahnung, wie dieser Unterschied passieren könnte - und wenn dies bedeutet, soll ich alle Anfragen in meinem Projekt ändern, um die Zeichenfolge-Notation ...
Ich bin mit MySQL Version 5.7.10
Laut Ihren Kommentaren habe ich alle Dienste deaktiviert, die in die Datenbank schreiben oder lesen und das Experiment wiederholen.
A) Die Ganzzahl Notation:
SET profiling=0;
SET profiling=1;
SELECT
COUNT(*)
FROM
incidents.incidents AS inc,
incidents.enrichment AS enr
WHERE
inc.Id <= 606734
AND inc.Id >= 1
AND inc.Id = enr.ParentTableId
AND (
enr.Enricher3State = 2
OR enr.Enricher4State = 2
OR enr.Enricher5State = 2
OR enr.Enricher9State = 2
);
SELECT
COUNT(*)
FROM
incidents.incidents AS inc,
incidents.enrichment AS enr
WHERE
inc.Id <= 606734
AND inc.Id >= 1
AND inc.Id = enr.ParentTableId
AND (
enr.Enricher3State = 2
OR enr.Enricher4State = 2
OR enr.Enricher5State = 2
OR enr.Enricher9State = 2
);
SELECT
COUNT(*)
FROM
incidents.incidents AS inc,
incidents.enrichment AS enr
WHERE
inc.Id <= 606734
AND inc.Id >= 1
AND inc.Id = enr.ParentTableId
AND (
enr.Enricher3State = 2
OR enr.Enricher4State = 2
OR enr.Enricher5State = 2
OR enr.Enricher9State = 2
);
SELECT
COUNT(*)
FROM
incidents.incidents AS inc,
incidents.enrichment AS enr
WHERE
inc.Id <= 606734
AND inc.Id >= 1
AND inc.Id = enr.ParentTableId
AND (
enr.Enricher3State = 2
OR enr.Enricher4State = 2
OR enr.Enricher5State = 2
OR enr.Enricher9State = 2
);
SELECT
COUNT(*)
FROM
incidents.incidents AS inc,
incidents.enrichment AS enr
WHERE
inc.Id <= 606734
AND inc.Id >= 1
AND inc.Id = enr.ParentTableId
AND (
enr.Enricher3State = 2
OR enr.Enricher4State = 2
OR enr.Enricher5State = 2
OR enr.Enricher9State = 2
);
SHOW PROFILES;
Ausführungszeit jeder Abfrage:
- 6,42429325
- 5,95059900
- 6,34392825
- 6,53041775
- 6,69593450
B) Der String Notation:
SET profiling=0;
SET profiling=1;
SELECT
COUNT(*)
FROM
incidents.incidents AS inc,
incidents.enrichment AS enr
WHERE
inc.Id <= 606734
AND inc.Id >= 1
AND inc.Id = enr.ParentTableId
AND (
enr.Enricher3State = '2'
OR enr.Enricher4State = '2'
OR enr.Enricher5State = '2'
OR enr.Enricher9State = '2'
);
SELECT
COUNT(*)
FROM
incidents.incidents AS inc,
incidents.enrichment AS enr
WHERE
inc.Id <= 606734
AND inc.Id >= 1
AND inc.Id = enr.ParentTableId
AND (
enr.Enricher3State = '2'
OR enr.Enricher4State = '2'
OR enr.Enricher5State = '2'
OR enr.Enricher9State = '2'
);
SELECT
COUNT(*)
FROM
incidents.incidents AS inc,
incidents.enrichment AS enr
WHERE
inc.Id <= 606734
AND inc.Id >= 1
AND inc.Id = enr.ParentTableId
AND (
enr.Enricher3State = '2'
OR enr.Enricher4State = '2'
OR enr.Enricher5State = '2'
OR enr.Enricher9State = '2'
);
SELECT
COUNT(*)
FROM
incidents.incidents AS inc,
incidents.enrichment AS enr
WHERE
inc.Id <= 606734
AND inc.Id >= 1
AND inc.Id = enr.ParentTableId
AND (
enr.Enricher3State = '2'
OR enr.Enricher4State = '2'
OR enr.Enricher5State = '2'
OR enr.Enricher9State = '2'
);
SELECT
COUNT(*)
FROM
incidents.incidents AS inc,
incidents.enrichment AS enr
WHERE
inc.Id <= 606734
AND inc.Id >= 1
AND inc.Id = enr.ParentTableId
AND (
enr.Enricher3State = '2'
OR enr.Enricher4State = '2'
OR enr.Enricher5State = '2'
OR enr.Enricher9State = '2'
);
SHOW PROFILES;
Ausführungszeit:
- 5,07188875
- 4,90356250
- 4,86164300
- 4,48403375
- 5,06533725
Wie Sie deutlich sehen können, ist die String-Notation noch schneller!
Das gleiche Verhalten auch von anderen Entwicklern von meinem Team erkannt wurde, so konnte ich vorübergehend Dummheit von mir ausschließen ...
Wahrscheinlich der InnoDB Puffer-Cache bei der Arbeit. Versuchen Sie es erneut, dieses Mal jede Abfrage zweimal hintereinander auszuführen. Verwerfen Sie das erste Ergebnis, melden Sie das zweite Ergebnis jeder Abfrage. Das heißt, Integer-Abfrage ausführen, Integer-Abfrage (dies melden), String-Abfrage, String-Abfrage (dies melden). Wenn die Ergebnisse immer noch variieren, bis zu jeweils 4, verwerfen Sie den ersten Stand und mitteln dann die verbleibenden 3 für jede Abfrage. –
Auch sollte es keine andere Aktivität in der Datenbank geben, um wirklich Äpfel mit Äpfeln zu vergleichen. –
Ich habe den Test entsprechend Ihrer Eingabe modifiziert - aber das Ergebnis ist immer noch das gleiche. – Andreas