Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Optymalizacja zapytań - trwa zbyt długo i zatrzymuje serwer

Dodanie indeksu pomaga w wielu przypadkach, ale masz podzapytanie dołączające do innego podzapytania, żaden indeks w twojej bieżącej tabeli nie pomoże ci przyspieszyć. Jedynym sposobem wykorzystania indeksów jest utworzenie tabeli tymczasowej.

Tak więc, jak wskazał Markus, musisz podzielić zapytanie na kilka mniejszych, które przechowują wyniki w tabeli tymczasowej. Następnie możesz dodać do nich indeksy i mam nadzieję, że przyspieszysz wyszukiwanie. Kolejną dobrą rzeczą w dzieleniu dużego zapytania na kilka mniejszych jest to, że możesz lepiej określić, która część jest wolniejsza i naprawić ją.

Użyłeś również jednego podzapytania dwa razy, co jest złe dla wydajności, ponieważ wynik nie został zbuforowany.

Oto przykład, jak możesz to zrobić:

DROP TEMPORARY TABLE IF EXISTS tmp_k;
CREATE TEMPORARY TABLE tmp_k
    ENGINE=Memory
SELECT 
    gps_unit_location.*,
    @i:= IF(((Speed_Kmh > 80) AND (@b = 0)), @i + 1, @i) AS IntervalID,
    @r:= IF(((Speed_Kmh > 80) AND (@b = 0)), 1, @r + 1) AS RowNumber,
    @b:= IF((Speed_Kmh > 80), 1, 0) AS IntervalCheck
FROM
    gps_unit_location,
    (SELECT @i:=0) i, 
    (SELECT @r:=0) r, 
    (SELECT @b:=0) b
ORDER BY
    dt,
    idgps_unit_location;

ALTER TABLE tmp_k ADD INDEX (IntervalID);

DROP TEMPORARY TABLE IF EXISTS tmp_max;
CREATE TEMPORARY TABLE tmp_max
    ENGINE=Memory
SELECT 
    IntervalID, 
    MAX(RowNumber) AS MaxRowNo
FROM
    temp_k
WHERE
    IntervalCheck = 1
GROUP BY 
    IntervalID;

ALTER TABLE tmp_max ADD INDEX (IntervalID);

SELECT 
    k.idgps_unit,
    MIN(k.dt) AS DT_Start,
    MIN(IF(k.RowNumber = 1, k.Lat, NULL)) AS Latitude_Start,
    MIN(IF(k.RowNumber = 1, k.Long, NULL)) AS Longitude_Start,
    MIN(IF(k.RowNumber = 1, k.Speed_kmh, NULL) AS Speed_Start,
    MAX(k.dt) AS DT_End,
    MIN(IF(k.RowNumber = m.MaxRowNo, k.Lat, NULL)) AS Latitude_End
    MIN(IF(k.RowNumber = m.MaxRowNo, k.Long, NULL)) AS Longitude_End
    MIN(IF(k.RowNumber = m.MaxRowNo, k.Speed_kmh, NULL)) AS Speed_End,
    AVG(Speed_kmh) AS Average_Speed,
    gu.name,
    gu.notes,
    gu.serial
FROM
    tmp_k AS k
    INNER JOIN tmp_max AS m
        USING(IntervalID)
    INNER JOIN gps_unit AS gu
        USING(idgps_unit)
    INNER JOIN user AS u
    ON (gu.idcustomer = u.idcustomer)
WHERE
    (k.IntervalCheck = 1) 
     AND (u.iduser = 14)
GROUP BY 
    k.IntervalID, 
    k.idgps_unit;

DROP TEMPORARY TABLE tmp_k;
DROP TEMPORARY TABLE tmp_max;


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. wywołaj zewnętrzny skrypt z wyzwalaczem mySQL WHITOUT sys_exec na ubuntu ARMHF

  2. czas trwania mysql i czas pobierania

  3. Jak usunąć wiodące i końcowe znaki w MySQL?

  4. Łączenie arkuszy kalkulacyjnych Google z MySQL za pomocą JDBC

  5. Jak zapisać wartości wielokrotnego wyboru w tabeli SQL? Jak powinien wyglądać stół?