sql >> Database teknologi >  >> RDS >> Mysql

Forespørgselsoptimering -- tager for lang tid og stopper serveren

Tilføjelse af et indeks hjælper i mange tilfælde, men du har en underforespørgsel, der slutter sig til en anden underforespørgsel, intet indeks på din nuværende tabel kan hjælpe dig med at fremskynde. Den eneste måde, du kan bruge indekser på her, er at oprette en midlertidig tabel.

Så som Markus påpegede, skal du opdele din forespørgsel i et par mindre, som gemmer deres resultater i en midlertidig tabel. Så kan du tilføje indekser til dem og forhåbentlig fremskynde din forespørgsel. En anden god ting ved at dele store forespørgsler op i et par mindre er, at du bedre kan profilere, hvilken del der er den langsommere og rette den.

Du har også brugt en underforespørgsel to gange, hvilket er dårligt for ydeevnen, da resultatet ikke blev cachelagret.

Her er et eksempel på, hvordan du kan gøre dette:

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. Giv tilladelser på tabelniveau i SQL Server

  2. Sådan sender du data til databasen ved hjælp af Fetch API i React.js

  3. Er der nogen forskel på at gemme samme værdi i forskellige heltalstyper?

  4. Kompliceret MySQL-forespørgsel