Tak tahu harus bagaimana lagi dengan yang ini. Saya punya satu tabel yang memiliki awal dan berhenti kolom dan saya ingin mengembalikan hasilnya bergabung dengan mulai dan dengan berhenti dan saya ingin perbedaan yang jelas antara keduanya. Sekarang kedua query berjalan dengan cepat:
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
Jadi yang ini membutuhkan 0,063. Tetapi jika saya menggabungkannya dalam UNION (tidak masalah apakah itu UNION ALL ATAU DISTINCT ATAU APA PUN) itu hanya membutuhkan sekitar 0,400 detik.
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)
Berikut adalah MENJELASKAN pada permintaan tunggal:
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
Dan di sini adalah MENJELASKAN untuk BERGABUNG:
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
Bantuan yang satu ini akan sangat dihargai. :)
EDIT:
Saya mendapatkan hasil yang tidak konsisten. Jika saya menghapus convert_tz misalnya dan mencoba untuk mendapatkan zona waktu di luar serikat saya mendapatkan hasil yang sangat cepat, tetapi jika saya mengubah nama hasilnya secara otomatis turun ke permintaan yang kurang kinerja yang sama:
SELECT
*,
GetCarrierTimezone(carrier_id) timezone
FROM
(
ini membutuhkan 0,374s
SELECT
*,
GetCarrierTimezone(carrier_id)
FROM
(
sementara ini membutuhkan 0,078 (kebanyakan lag dari db ke mesin saya) ..
Jawaban:
Saya berharap ini terjadi karena ORDER OLEH Anda miliki di sana.
Coba ini di bagian pertama UNION:
Dan ini di bagian kedua:
Dan kemudian ganti
ORDER BY
denganDengan kata lain, hapus kebutuhan untuk IF dalam urutan oleh.
sumber
Dalam kasus yang sangat mirip, saya perhatikan dari daftar proses mysql perilaku yang sangat buruk dari 'copy to temp table' (menyalin Apa? Saya tidak tahu). Saya pikir mysql tergoda 'pendekatan terbaik' untuk query, tetapi dalam kasus ini gagal, jadi menggunakan kode untuk 'menggabungkan' hasil 2-query bekerja dengan baik.
sumber
Alasan utama untuk menjalankan sql union lebih lambat adalah bahwa union menyebabkan mysqld untuk membuat tabel sementara internal. Ini hanya membuat tabel untuk UNION ALL dan tabel dengan indeks (untuk menghapus duplikat) untuk UNION DISTINCT.
Semoga ini membantu.
sumber