2016-06-28 10 views
1

Ich habe ein Projekt abgerufen, das aufgrund einer SQL-Abfrage eine lange Zeit benötigt.Eine SQL-Abfrage verbessern

Ich mag gerne wissen, ob Sie einen Weg kennen, es zu verbessern. Zumindest, wenn es einen Weg gibt, es zu verbessern.

Von dem, was ich weiß, wird die Abfrage zurück 1500 Zeilen und macht eine Summe und die Anzahl von anderen Tabellen.

SELECT 
p.id, 
p.datecreate, 
p.title, 
p.address, 
p.address2, 
p.code_postal, 
p.ville, 
p.description, 
p.description_admin, 
p.idstatut, 
p.idstatut_admin, 
p.reference, 
p.star, 
p.logo, 
p.deleted, 
cc.value as starcolor, 
p.idsociete, 
soc.nom as societe_nom, 
s.titlestatut, 
s.fontcolor, 
s.label as label, 
sa.titlestatut as titlestatut_admin, 
sa.fontcolor as fontcolor_admin, 
sa.label as label_admin, 
(SELECT SUM(nbr) FROM plans as cplans WHERE cplans.idprojets = p.id) as count_commandes, 
(SELECT count(id) FROM files as cfiles WHERE cfiles.idprojets = p.id AND cfiles.folder = '1' AND cfiles.bat_valid = '0') as count_averifier, 
(SELECT count(rowid) FROM files_modif_title as cfmt WHERE cfmt.idprojets = p.id AND cfmt.statut = '7' AND cfmt.hide = '0') as count_modif_nohide, 
(SELECT count(rowid) FROM files_modif_title as cfmt WHERE cfmt.idprojets = p.id AND cfmt.statut = '7' AND cfmt.hide IN (1)) as count_modif_hide, 
(SELECT count(id) FROM files as cfiles WHERE cfiles.idprojets = p.id AND cfiles.folder = '2' AND cfiles.bat_valid = '0') as count_bat_attente, 
(SELECT count(id) FROM files as cfiles WHERE cfiles.idprojets = p.id AND cfiles.folder = '2' AND cfiles.bat_valid = '1') as count_bat_valider 
FROM projets as p INNER JOIN societe AS soc ON p.idsociete = soc.id 
INNER JOIN statuts AS s ON p.idstatut = s.id 
INNER JOIN statuts AS sa ON p.idstatut_admin = sa.id 
LEFT JOIN const AS cc ON cc.name = p.star AND cc.parent = 'star' 
WHERE p.idstatut IN (3) 
AND p.deleted = 0 
GROUP BY p.id 
ORDER BY p.datecreate DESC 

Danke Jungs!

bearbeiten -----

Hier ist, was ich tat, könnte es besser sein?

Dank dem, was Sie gesagt haben, war das Hauptproblem die 6 SELECT sind in der SELECT-Klausel eingebettet. Diese werden für jeden von der Anwendung zusammengestellten Datensatz ausgewertet, sodass 1500 x 6 = 9000 Abfragen ausgeführt werden. Dadurch hatte ich 9001 Abfragen und jetzt nur 7, da Unterabfragen nur einmal zur Laufzeit ausgewertet werden. Ist das korrekt ?

+1

Die allgemeine GROUP BY-Regel sagt: Wenn ein GROUP BY-Klausel angegeben ist, muss jede Spalte Verweis in der SELECT-Liste entweder eine Gruppierungsspalte identifizieren oder das Argument einer Set-Funktion sein. – jarlh

+1

Das sieht gut aus. Sie sollten sicherstellen, dass Sie über die richtigen Indizes verfügen. –

Antwort

2

beitreten Dies ist der Teil, den Sie trotzig verbessern wollen:

(SELECT SUM(nbr) FROM plans as cplans WHERE cplans.idprojets = p.id) as count_commandes, 
(SELECT count(id) FROM files as cfiles WHERE cfiles.idprojets = p.id AND cfiles.folder = '1' AND cfiles.bat_valid = '0') as count_averifier, 
(SELECT count(rowid) FROM files_modif_title as cfmt WHERE cfmt.idprojets = p.id AND cfmt.statut = '7' AND cfmt.hide = '0') as count_modif_nohide, 
(SELECT count(rowid) FROM files_modif_title as cfmt WHERE cfmt.idprojets = p.id AND cfmt.statut = '7' AND cfmt.hide IN (1)) as count_modif_hide, 
(SELECT count(id) FROM files as cfiles WHERE cfiles.idprojets = p.id AND cfiles.folder = '2' AND cfiles.bat_valid = '0') as count_bat_attente, 
(SELECT count(id) FROM files as cfiles WHERE cfiles.idprojets = p.id AND cfiles.folder = '2' AND cfiles.bat_valid = '1') as count_bat_valider 

Sie verwenden können bedingte Aggregation für diese und nur ein einziges Mal die Tabellen beitreten:

count(nbr) as.., 
count(CASE WHEN cfiles.folder = '1' and cfiles.bat_valid = '0' then id END) as .., 
count(CASE WHEN cfiles.folder = '2' and cfiles.bat_valid = '0' then id END) as .., 
count(CASE WHEN cfiles.folder = '2' and cfiles.bat_valid = '1' then id END) as .., 
........ 

In der

JOIN files cfiles 
ON(cfiles.idprojets = p.id) 

Sie schließt sich genau das gleiche für files_modif_title

+0

Danke, das ist eine nette Möglichkeit, es zu verbessern! Ich verdiene 80% Zeit zur Laufzeit: D – Majestic

1
  1. Hoffentlich ist Ihr Haupttabelle hat Indizierung
  2. Stattdessen Unterabfrage verwenden, verwenden
+0

Danke, es hat mir geholfen, eine neue Version zu erstellen! – Majestic

1

Versuch,

SELECT 
p.id, 
p.datecreate, 
p.title, 
p.address, 
p.address2, 
p.code_postal, 
p.ville, 
p.description, 
p.description_admin, 
p.idstatut, 
p.idstatut_admin, 
p.reference, 
p.star, 
p.logo, 
p.deleted, 
cc.value as starcolor, 
p.idsociete, 
soc.nom as societe_nom, 
s.titlestatut, 
s.fontcolor, 
s.label as label, 
sa.titlestatut as titlestatut_admin, 
sa.fontcolor as fontcolor_admin, 
sa.label as label_admin, 
count (case when cfiles.folder = '2' AND cfiles.bat_valid = '0' then 1 end) count_bat_attente, 
count (case when cfiles.folder = '1' AND cfiles.bat_valid = '0' then 1 end) count_averifier, 
count (case when cfiles.folder = '2' AND cfiles.bat_valid = '1' then 1 end) count_bat_valider, 
SUM(nbr) as count_commandes, 
count (case when cfmt.statut = '7' AND cfmt.hide = '0' then 1 end) count_modif_nohide, 
count (case when cfmt.statut = '7' AND cfmt.hide IN (1) then 1 end) count_modif_hide 

FROM projets as p INNER JOIN societe AS soc ON p.idsociete = soc.id 
INNER JOIN statuts AS s ON p.idstatut = s.id 
INNER JOIN statuts AS sa ON p.idstatut_admin = sa.id 
left join files on files.idprojets=p.id 
left join plans cplans on cplans.idprojets = p.id 
left join files_modif_title cfmt on cfmt.idprojets = p.id 
LEFT JOIN const AS cc ON cc.name = p.star AND cc.parent = 'star' 
WHERE p.idstatut IN (3) 
AND p.deleted = 0 
GROUP BY p.id 
ORDER BY p.datecreate DESC 
1

Um Ihre Frage zu beantworten: "Hier, was ich tat, könnte es besser sein?", .. .

Während Ihre 9001 Logik gültig ist, gibt es ein weiteres Problem ... LEFT JOIN (SELECT ...) eine temporäre Tabelle von einigen n bauen Umbra (1500?) Reihen. Wenn Sie eine Version vor 5.6 ausführen, haben diese tmp-Tabellen keinen Index und müssen wiederholt überprüft werden. Jetzt sprechen wir von 1500 * 1500 * 6 = Millionen von Operationen, nicht nur von 9001.

Selbst mit 5.6 gibt es den zusätzlichen Schritt (6-mal), um den optimalen Index zu finden und aufzubauen.

Aber ist Ihre eigentliche Frage „wie kann ich das beschleunigen?“. Die anderen haben gute Arbeit geleistet, um das zu beantworten.