UNION chậm nhưng cả hai truy vấn đều nhanh


11

Không có gì khác để làm về điều này. Tôi có một bảng có cột bắt đầu và cột dừng và tôi muốn trả về kết quả của bảng đã tham gia cả bằng cách bắt đầu và dừng lại và tôi muốn phân biệt rõ ràng giữa hai bảng. Bây giờ cả hai truy vấn chạy nhanh tách biệt:

SELECT
            UNIX_TIMESTAMP(CONVERT_TZ(start_dev, '+00:00', GetCarrierTimezone(a0.carrier_id))) AS alertStart,
            NULL AS alertStop,
            c0.name AS carrier_name,
            carrier_image,
            l0.Latitude,
            l0.Longitude
        FROM
            carriers AS c0
                INNER JOIN start_stop AS a0 ON a0.carrier_id = c0.id
                    INNER JOIN pcoarg AS l0 ON a0.startLogId = l0.id
        WHERE
                FIND_IN_SET(a0.carrier_id, '89467,1,64578,222625,45013') > 0
            AND
                start_dev > '2013-03-11 11:46:48'
            AND 
                start_dev = (SELECT MIN(start_dev) FROM start_stop AS a1 WHERE a0.carrier_id = a1.carrier_id AND DATE(a1.start_dev) = DATE(a0.start_dev))
        AND IsNotificationInSchedule(22, start_dev) > 0

Vì vậy, cái này mất 0,063. Nhưng nếu tôi kết hợp nó trong một UNION (không quan trọng nếu đó là UNION ALL HOẶC DISTINCT HOẶC WHATEVER) thì chỉ mất khoảng 0.400 giây.

SELECT * FROM
(
    (
        SELECT
            UNIX_TIMESTAMP(CONVERT_TZ(start_dev, '+00:00', GetCarrierTimezone(a0.carrier_id))) AS alertStart,
            NULL AS alertStop,
            c0.name AS carrier_name,
            carrier_image,
            l0.Latitude,
            l0.Longitude
        FROM
            carriers AS c0
                INNER JOIN start_stop AS a0 ON a0.carrier_id = c0.id
                    INNER JOIN pcoarg AS l0 ON a0.startLogId = l0.id
        WHERE
                FIND_IN_SET(a0.carrier_id, '89467,1,64578,222625,45013') > 0
            AND
                start_dev > '2013-03-11 11:46:48'
            AND 
                start_dev = (SELECT MIN(start_dev) FROM start_stop AS a1 WHERE a0.carrier_id = a1.carrier_id AND DATE(a1.start_dev) = DATE(a0.start_dev))
            AND IsNotificationInSchedule(22, start_dev) > 0
    ) UNION ALL (
        SELECT
            NULL AS alertStart,
            UNIX_TIMESTAMP(CONVERT_TZ(stop_dev, '+00:00', GetCarrierTimezone(a0.carrier_id))) AS alertStop,
            c0.name AS carrier_name,
            carrier_image,
            l0.Latitude,
            l0.Longitude
        FROM
            start_stop AS a0
                INNER JOIN carriers AS c0 ON a0.carrier_id = c0.id
                    INNER JOIN pcoarg AS l0 ON a0.stopLogId = l0.id
        WHERE
                FIND_IN_SET(a0.carrier_id, '89467,1,64578,222625,45013') > 0
            AND
                stop_dev > '2013-03-11 11:46:48'
            AND 
                stop_dev = (SELECT MAX(stop_dev) FROM start_stop AS a1 WHERE a0.carrier_id = a1.carrier_id AND DATE(a1.stop_dev) = DATE(a0.stop_dev))
            AND IsNotificationInSchedule(22, start_dev) > 0
    )
) AS startStops
ORDER BY IF(alertStart IS NULL, alertStop, alertStart)

Đây là GIẢI THÍCH cho một truy vấn duy nhất:

1   PRIMARY c0  ALL PRIMARY             17  Using where
1   PRIMARY a0  ref PRIMARY,startstop_carriers_stopdev_idx,georefidx,startstop_carriers_startdev_idx    startstop_carriers_stopdev_idx  4   test_backoffice.c0.id   72  Using where
1   PRIMARY l0  ref id ASC  id ASC  4   test_backoffice.a0.startLogId   1   Using where
2   DEPENDENT SUBQUERY  a1  ref PRIMARY,startstop_carriers_stopdev_idx,georefidx,startstop_carriers_startdev_idx    startstop_carriers_stopdev_idx  4   test_backoffice.a0.carrier_id   72  Using where; Using index

Và đây là GIẢI THÍCH cho THAM GIA:

1   PRIMARY <derived2>  system                  0   const row not found
2   DERIVED c0  ALL PRIMARY             17  Using where
2   DERIVED a0  ref PRIMARY,startstop_carriers_stopdev_idx,georefidx,startstop_carriers_startdev_idx    startstop_carriers_stopdev_idx  4   test_backoffice.c0.id   72  Using where
2   DERIVED l0  ref id ASC  id ASC  4   test_backoffice.a0.startLogId   1   Using where
3   DEPENDENT SUBQUERY  a1  ref PRIMARY,startstop_carriers_stopdev_idx,georefidx,startstop_carriers_startdev_idx    startstop_carriers_stopdev_idx  4   test_backoffice.a0.carrier_id   72  Using where; Using index
4   UNION   c0  ALL PRIMARY             17  Using where
4   UNION   a0  ref PRIMARY,startstop_carriers_stopdev_idx,georefidx,startstop_carriers_startdev_idx    startstop_carriers_stopdev_idx  4   test_backoffice.c0.id   72  Using where
4   UNION   l0  ref id ASC  id ASC  4   test_backoffice.a0.stopLogId    1   Using where
5   DEPENDENT SUBQUERY  a1  ref PRIMARY,startstop_carriers_stopdev_idx,georefidx,startstop_carriers_startdev_idx    startstop_carriers_stopdev_idx  4   test_backoffice.a0.carrier_id   72  Using where; Using index
    UNION RESULT    <union2,4>  ALL                     

Trợ giúp về điều này sẽ được đánh giá rất cao. :)

BIÊN TẬP:

Tôi đang nhận được kết quả không nhất quán. Ví dụ: nếu tôi loại bỏ convert_tz và cố gắng lấy múi giờ bên ngoài liên kết, tôi sẽ nhận được kết quả rất nhanh, nhưng nếu tôi đổi tên kết quả, nó sẽ tự động chuyển sang cùng một truy vấn dưới mức:

SELECT
    *,
    GetCarrierTimezone(carrier_id) timezone
FROM
(

cái này mất 0,374

SELECT
    *,
    GetCarrierTimezone(carrier_id)
FROM
(

trong khi điều này mất 0,078 (chủ yếu là độ trễ từ db đến máy của tôi) ..


Đơn giản nhất sẽ là chạy chúng riêng biệt và kết hợp các kết quả trong ứng dụng.
ypercubeᵀᴹ

chào @ypercube, điều đó đã vượt qua tâm trí của tôi :) nhưng thật xấu xí khi làm điều đó và duy trì mã đó. Ngoài ra tôi vẫn phải sắp xếp kết quả bằng php.
helderjsm

Tôi có nghĩa là chạy 2 truy vấn với sắp xếp mong muốn. Sau đó, bạn chỉ cần hợp nhất trong php (không sắp xếp).
ypercubeᵀᴹ

1
Việc sắp xếp không tuyến tính. Kết quả của truy vấn 1 có thể ở giữa các kết quả của truy vấn 2.
helderjsm

1
Tôi không nghĩ @ypercube cho rằng kết quả không trùng lặp: một 'hợp nhất' rẻ hơn / dễ dàng hơn nhiều so với cách thực hiện trong php. Tất nhiên, khắc phục sự cố trong SQL nếu có thể sẽ là một giải pháp tốt hơn nhiều :)
Jack nói hãy thử topanswers.xyz

Câu trả lời:


1

Tôi hy vọng điều này sẽ xảy ra vì LỆNH B BYNG bạn có trong đó.

Hãy thử điều này trong phần đầu tiên của ĐOÀN:

SELECT
            UNIX_TIMESTAMP(CONVERT_TZ(start_dev, '+00:00', GetCarrierTimezone(a0.carrier_id))) AS alertFoo,
            /* NULL AS alertStop, */

Và điều này trong phần thứ hai:

SELECT
            /* NULL AS alertStart, */
            UNIX_TIMESTAMP(CONVERT_TZ(stop_dev, '+00:00', GetCarrierTimezone(a0.carrier_id))) AS alertFoo,

Và sau đó thay thế ORDER BYbằng

ORDER BY alertFoo

Nói cách khác, loại bỏ sự cần thiết của IF theo thứ tự bằng cách.


Xin chào Thomas, Trước hết cảm ơn bạn đã phát lại. Giống như tôi đã nói trong một bài viết trước đây, điều này đã được sửa chữa cách đây một thời gian. Vấn đề là tôi cần phân biệt giữa cảnh báo 1 và cảnh báo 2. Trong mọi trường hợp, thứ tự được thực hiện dựa trên kết quả của các phép nối và không phải trên chính phép nối. Không có nhiều kết quả để chứng minh sự chậm chạp của truy vấn.
helderjsm

0

Trong một trường hợp rất giống nhau, tôi nhận thấy từ danh sách quy trình của mysql hành vi rất xấu của 'sao chép vào bảng tạm thời' (sao chép những gì? Tôi không biết). Tôi nghĩ mysql đã cám dỗ một 'cách tiếp cận tốt nhất' để truy vấn, nhưng trong trường hợp này đã thất bại, vì vậy sử dụng mã để 'hợp nhất' kết quả 2 truy vấn hoạt động tốt.


Hi realtebo, Cảm ơn cho đầu vào. Điều này bây giờ hơi cũ, nhưng đối với những gì tôi nhớ sự không nhất quán là bởi vì một số cách mysql lưu trữ một số kết quả và không phải là kết quả khác. Cuối cùng tôi đã tạo lại truy vấn theo cách hiệu quả hơn đặc biệt bằng cách theo dõi các giá trị tôi cần trong một bảng riêng biệt làm cho các chỉ mục hiệu quả hơn.
helderjsm

0

Lý do chính khiến công đoàn sql chạy chậm hơn là do công đoàn khiến mysqld tạo ra một bảng tạm thời nội bộ. Nó chỉ tạo một bảng cho UNION ALL và một bảng có chỉ mục (để loại bỏ các bản sao) cho một DISTINCT UNION.

Hi vọng điêu nay co ich.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.