Verwendung eines Parameters in einer gespeicherten MySQL-Prozedur WHERE-CLAUSE verlangsamt die Leistung

8

Ich habe eine gespeicherte Prozedur wie folgt deklariert:

%Vor%

Wenn ich die Verwendung des Parameters dom_id durch eine statische Ganzzahl ersetze, zB:

%Vor%

MySQL-Version: 5.5.41

ERKLÄREN:

%Vor%

SHOW CREATE TABLE-Domäne:

%Vor%

Die Prozedur dauert 0,06s, um ausgeführt zu werden, während der Parameter "dom_id" verwendet wird und den Integer-Wert von 1 übergibt, führt dies zu einer Ausführungszeit von 5.070s. Irgendwelche Ideen?

    
sboss 18.08.2015, 08:40
quelle

5 Antworten

4

Wenn Sie den ganzen Weg dynamisch gehen, habe ich Tests verwendet, um Ihren ursprünglichen proc nicht zu überschreiben, stellen Sie auch sicher, dass Sie nicht bereits einen testing proc haben

%Vor%

Dann verwenden Sie

%Vor%     
Mihai 18.08.2015, 09:22
quelle
8

Wie bei der Frage möchte @sboss das Verhalten von:

kennen %Vor%

Dieses Verhalten kann leicht verstanden werden, wenn wir sehen, wie die mysql-Engine funktioniert.

  

MySQL Engine speichert Abfrage und Ergebnis zwischen. Der Abfrage-Cache speichert den Text   einer SELECT-Anweisung zusammen mit dem entsprechenden Ergebnis, das war   an den Kunden gesendet. Wenn später eine identische Aussage erhalten wird,   Server ruft die Ergebnisse aus dem Abfrage-Cache ab, statt zu analysieren   und die Anweisung erneut ausführen.

Daher ist es in Ihrem Fall höchstwahrscheinlich, dass execution time of 5.070s gefunden wird, wenn die Abfrage tatsächlich von der MySQL-Engine analysiert und ausgeführt wird und execution time of 0.06s gefunden wird, wenn die Ergebnismenge aus dem Abfrage-Cache abgerufen wurde.

Bitte lesen Sie die Dokumentation für Details: Ссылка

    
seahawk 23.08.2015 21:46
quelle
5

Optimierung 1

Teil der Verlangsamung ist die wiederholt ausgeführte "abhängige Unterabfrage":

%Vor%

Gemäß EXPLAIN müssen alle ~ 8703 Zeilen von link jedes Mal gescannt werden.

Ich glaube nicht, dass es innerhalb derselben Abfrage vereinfacht werden kann. Stattdessen denke ich, dass dies nützlich sein wird:

%Vor%

Dann

%Vor%

Sie können testen, ob der PREPARE -Ansatz schneller ist. In einem (einfacheren) Test, den ich gemacht habe, schien das keine Rolle zu spielen.

Optimierung 2

Eine andere potenzielle Beschleunigung besteht darin, die GROUP_CONCATs in Unterabfragen anstatt des Sammelns von vielen Zeilen durchzuführen und dann zu kollabieren. Beachten Sie, dass Sie GROUP BY verwenden mussten. Diese Technik kann dies möglicherweise beseitigen. Zum Beispiel:

%Vor%

- & gt;

%Vor%

Der Grund, warum möglicherweise ist, kann beobachtet werden, wenn Sie dies sowohl mit Ihrer Variante als auch mit meiner Variante tun:

%Vor%

Ihre Variante wird (unter der Annahme vieler Kategorien usw.) einen viel größeren COUNT haben. Das bedeutet, dass Ihre Abfrage eine viel größere Tabelle erstellt, um sie an GROUP BY und ORDER BY zu füttern. Daher langsamer.

Optimierung 3

Wenn Sie alle Aggregate ( GROUP_CONCAT ) loswerden, dann sollten Sie INDEX(country, name) weiter optimieren, indem Sie die beiden FILESORTs loswerden.

    
Rick James 21.08.2015 03:42
quelle
0

Sie sagen hier, dass Sie die Daten schnell abrufen können, während Sie WHERE verwenden   Domänen.land = 1 Anstatt von WOHER   domain.country = dom_id aber ich bin nicht in der Lage, where-Klausel auf domain.country in Ihrer Abfrage zu sehen. Kannst du das bitte klären?

Aber im Allgemeinen ist was passiert

  1. Where-Klausel wird schneller auf Integer-Werten
  2. ausgeführt
  3. Wenn Sie where-Klausel für eine Spalte sehr häufig ausführen, können Sie diese Spalte indizieren. Die Indexierung hilft beim schnelleren Abruf. Gleichzeitig müssen Sie jedoch beim Indexieren von Spalten eine kluge Entscheidung treffen.

Bitte lassen Sie mich wissen, wenn Sie nach etwas anderem suchen.

    
Jaydatt 18.08.2015 09:05
quelle
0

Löschen Sie zuerst Ihre Zweifel, warum die Abfrage Zeit braucht, wenn Sie den Wert über Parameter übergeben. Da Rick und Jaydatt in ihren Beiträgen erwähnt haben, dass der Cache abgefragt werden kann, können Sie diese Zweifel zunächst beheben, indem Sie Ihre Abfrage mit dem Zusatz SQL_NO_CACHE wie SELECT SQL_NO_CACHE domain.id, IFNULL(domain.indexed, '-') AS indexed,....

ausführen

Ich denke, jetzt solltest du ca. Gleichzeitig durch beide Abfragen.

Auch für die Optimierung dieser Abfrage hat Rick Ihnen so viele nützliche Optionen zur Verfügung gestellt, dass Sie die untenstehende Option auch zusammen mit diesen überprüfen können.

Überprüfen Sie zuerst, ob das Feld link.from_domain indiziert ist oder nicht, da explain zeigt, dass alle Zeilen aus der Linktabelle scannen.

Sie können auch die Abfrageleistung mit folgendem Ansatz überprüfen:

%Vor%     
Zafar Malik 26.08.2015 06:03
quelle