Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Tối ưu hóa truy vấn - mất quá nhiều thời gian và dừng máy chủ

Thêm chỉ mục giúp ích trong nhiều trường hợp, nhưng bạn có một truy vấn con tham gia một truy vấn con khác, không chỉ mục nào trên bảng hiện tại của bạn có thể giúp bạn tăng tốc. Cách duy nhất bạn có thể sử dụng các chỉ mục ở đây là tạo bảng tạm thời.

Vì vậy, như Markus đã chỉ ra, bạn cần chia truy vấn của mình thành một vài truy vấn nhỏ hơn để lưu trữ kết quả của chúng trong một bảng tạm thời. Hơn nữa, bạn có thể thêm chỉ mục cho chúng và hy vọng tăng tốc truy vấn của bạn. Một điều tốt khác khi chia truy vấn lớn thành một vài truy vấn nhỏ hơn là bạn có thể xác định rõ hơn phần nào chậm hơn và sửa phần đó.

Bạn cũng đã sử dụng một truy vấn con hai lần, điều này có hại cho hiệu suất do kết quả không được lưu vào bộ nhớ đệm.

Đây là một ví dụ về cách bạn có thể làm điều này:

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. Không thể khai báo lại một hàm đã khai báo trước đó

  2. Không thể tìm nạp id hàng bằng pdo

  3. Nhóm các hàng tương tự bên cạnh nhau trong MySQL

  4. mysqli_real_escape_string và vấn đề dấu ngoặc kép

  5. trình kích hoạt xóa mysql