2016-10-09 2 views
0

Ich habe 2 Tabellen verknüpft:Zeitabfrageleistung links eine Ansicht

describe CONSUMO 

Field  Type  Null Key  Default  Extra 
idconsumo int(11)  NO  PRI  NULL  auto_increment 
idkey  int(11)  NO  MUL  NULL  
ip   varchar(50) NO    Unknown 
fechahora datetime NO    NULL  


describe CONTRATADO 

Field  Type  Null Key  Default  Extra 
idkey  int(11)  NO  PRI  NULL  auto_increment 
idusuario int(11)  NO  MUL  NULL  
idproducto int(11)  NO  MUL  NULL  
key   varchar(64) NO  MUL  NULL  
descripcion varchar(50) YES    "API KEY" 
peticiones int(11)  YES    NULL  
caducidad datetime YES    NULL  

und einen Blick (die letzten 30 Tage von NOW() zurück):

CREATE VIEW `last_30_days` AS 
    SELECT 
     DATE_FORMAT((NOW() - INTERVAL ((`units`.`i` + (`tens`.`i` * 10)) + (`hundreds`.`i` * 100)) DAY), 
       '%M %e') AS `fecha`, 
     DATE_FORMAT((NOW() - INTERVAL ((`units`.`i` + (`tens`.`i` * 10)) + (`hundreds`.`i` * 100)) DAY), 
       '%Y%m%d') AS `fecha_order` 
    FROM 
     ((`0_9_range` `units` 
     JOIN `0_9_range` `tens`) 
     JOIN `0_9_range` `hundreds`) 
    WHERE 
     ((NOW() - INTERVAL ((`units`.`i` + (`tens`.`i` * 10)) + (`hundreds`.`i` * 100)) DAY) BETWEEN (NOW() - INTERVAL 1 MONTH) AND NOW()) 

Immer, wenn ich eine Abfrage ausführen, wie zum Beispiel:

SELECT sub1.fecha, COUNT(idconsumo) as consumo 
FROM `last_30_days` `sub1` 
LEFT JOIN `CONSUMO` ON sub1.fecha = DATE_FORMAT(fechahora, "%M %e") 
LEFT JOIN `CONTRATADO` ON CONSUMO.idkey = CONTRATADO.idkey 
WHERE idusuario IS NULL OR idusuario = 1 
GROUP BY `sub1`.`fecha` 
ORDER BY `sub1`.`fecha_order` 

es dauert einige Zeit (~ 20 Sekunden).

Hier ist eine der Abfrage erklären:

id  select_type  table         type possible_keys key  key_len ref      rows Extra 
1  PRIMARY   <derived3>        ALL  NULL   NULL NULL NULL     10  "Using temporary; Using filesort" 
1  PRIMARY   <derived13>        ALL  NULL   NULL NULL NULL     10  "Using join buffer" 
1  PRIMARY   <derived23>        ALL  NULL   NULL NULL NULL     10  "Using where; Using join buffer" 
1  PRIMARY   CONSUMO         ALL  NULL   NULL NULL NULL     908553 
1  PRIMARY   CONTRATADO        eq_ref PRIMARY   PRIMARY 4  c1geoapi.CONSUMO.idkey 1  "Using where" 
23  DERIVED   NULL         NULL NULL   NULL NULL NULL     NULL "No tables used" 
24  UNION   NULL         NULL NULL   NULL NULL NULL     NULL "No tables used" 
25  UNION   NULL         NULL NULL   NULL NULL NULL     NULL "No tables used" 
26  UNION   NULL         NULL NULL   NULL NULL NULL     NULL "No tables used" 
27  UNION   NULL         NULL NULL   NULL NULL NULL     NULL "No tables used" 
28  UNION   NULL         NULL NULL   NULL NULL NULL     NULL "No tables used" 
29  UNION   NULL         NULL NULL   NULL NULL NULL     NULL "No tables used" 
30  UNION   NULL         NULL NULL   NULL NULL NULL     NULL "No tables used" 
31  UNION   NULL         NULL NULL   NULL NULL NULL     NULL "No tables used" 
32  UNION   NULL         NULL NULL   NULL NULL NULL     NULL "No tables used" 
NULL "UNION RESULT" <union23,24,25,26,27,28,29,30,31,32> ALL  NULL   NULL NULL NULL     NULL  
13  DERIVED   NULL         NULL NULL   NULL NULL NULL     NULL "No tables used" 
14  UNION   NULL         NULL NULL   NULL NULL NULL     NULL "No tables used" 
15  UNION   NULL         NULL NULL   NULL NULL NULL     NULL "No tables used" 
16  UNION   NULL         NULL NULL   NULL NULL NULL     NULL "No tables used" 
17  UNION   NULL         NULL NULL   NULL NULL NULL     NULL "No tables used" 
18  UNION   NULL         NULL NULL   NULL NULL NULL     NULL "No tables used" 
19  UNION   NULL         NULL NULL   NULL NULL NULL     NULL "No tables used" 
20  UNION   NULL         NULL NULL   NULL NULL NULL     NULL "No tables used" 
21  UNION   NULL         NULL NULL   NULL NULL NULL     NULL "No tables used" 
22  UNION   NULL         NULL NULL   NULL NULL NULL     NULL "No tables used" 
NULL "UNION RESULT" <union13,14,15,16,17,18,19,20,21,22> ALL  NULL   NULL NULL NULL     NULL  
3  DERIVED   NULL         NULL NULL   NULL NULL NULL     NULL "No tables used" 
4  UNION   NULL         NULL NULL   NULL NULL NULL     NULL "No tables used" 
5  UNION   NULL         NULL NULL   NULL NULL NULL     NULL "No tables used" 
6  UNION   NULL         NULL NULL   NULL NULL NULL     NULL "No tables used" 
7  UNION   NULL         NULL NULL   NULL NULL NULL     NULL "No tables used" 
8  UNION   NULL         NULL NULL   NULL NULL NULL     NULL "No tables used" 
9  UNION   NULL         NULL NULL   NULL NULL NULL     NULL "No tables used" 
10  UNION   NULL         NULL NULL   NULL NULL NULL     NULL "No tables used" 
11  UNION   NULL         NULL NULL   NULL NULL NULL     NULL "No tables used" 
12  UNION   NULL         NULL NULL   NULL NULL NULL     NULL "No tables used" 
NULL "UNION RESULT" <union3,4,5,6,7,8,9,10,11,12>   ALL  NULL   NULL NULL NULL     NULL  

Was kann ich tun, um meine Anfrage zu verbessern? Warum dauert das so lange?

+0

Nimmt eine Auswahl aus der Ansicht auch eine lange Zeit in Anspruch? – sagi

+0

Nein, die Auswahl von '*' aus den 'last_30_days' ist so schnell wie es geht. – alexandernst

Antwort

1

Die meisten Probleme sind hier:

LEFT JOIN `CONSUMO` ON sub1.fecha = DATE_FORMAT(fechahora, "%M %e") 

Insbesondere:

  • nicht LEFT Verwenden Sie; Sie möchten, dass alle Zeilen und keine zusätzlichen korrekt sind? Verwenden Sie also eine einfache JOIN.

  • Do Index fechahora.

  • Nicht verwenden DESCRIBE; es ist weniger beschreibend als SHOW CREATE TABLE.

  • Anstatt die letzten 30 Tage immer wieder neu zu berechnen; habe eine lange Tabelle mit Datumsangaben für mehrere Jahre und verwende eine WHERE-Klausel, um die gewünschten Zeilen zu begrenzen.

  • Verstecken Sie nicht fechahora innerhalb einer Funktion. Neuordnen der Abfrage, so dass es wie

    ON fechahora sieht> = ... sub1.fecha ... UND fechahora < ... sub1.fecha + INTERVAL 1 TAG ...

Die ... muss sein, was immer nötig ist, um die Umkehrung von "% M% e" zu machen. Sie wären wahrscheinlich besser dran, wenn Sie last_30_days ändern, um einen einfachen DATE Datentyp zu berechnen. Wenn/wenn Sie eine bestimmte Formatierung in der Ausgabe benötigen, tun Sie es in der SELECT.

+0

Die Ausgabe meiner Abfrage, wenn Sie 'left join' nicht verwenden, während Sie Änderungen vorgeschlagen haben (tatsächlich wird nichts zurückgegeben). Ich habe einen Index für "Fechahora" gemacht, aber die Performance ist immer noch genau dieselbe. 'last_30_days' berechnet bereits einen' DATE' Typ. Über die Ansicht gegenüber der Tabelle, die einige Jahre Daten enthält, bin ich nicht wirklich sicher, ob dies eine elegante Methode ist oder dass es die Dinge besser macht, da die Auswahl aus dieser Sicht so schnell ist wie eine Auswahl. – alexandernst

+0

Nachdem ich ein paar Stunden mehr damit verbracht habe, habe ich die Wurzel des Problems gefunden. Sie haben einen Punkt in der letzten Sache, die Sie gesagt haben. Die Abfrage dauert so lange, weil sie jede einzelne DATETIME-Spalte in DATE konvertieren muss. – alexandernst

Verwandte Themen