UNION धीमा है लेकिन दोनों प्रश्न अलग-अलग हैं


11

दुन्नो इस बारे में और क्या करे। मेरे पास एक तालिका है जिसमें एक शुरुआत और एक स्टॉप कॉलम है और मैं इसके परिणामों को वापस शुरू और स्टॉप दोनों में शामिल करना चाहता हूं और मैं दोनों के बीच स्पष्ट अंतर चाहता हूं। अब दोनों प्रश्न तेजी से अलग-अलग चलते हैं:

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

तो यह एक 0.063 लेता है। लेकिन अगर मैं इसे UNION में संयोजित करता हूं (इससे कोई फर्क नहीं पड़ता कि यह UNION ALL OR DISTINCT OR WHATEVER है) तो बस लगभग 0.400 सेकंड लगते हैं।

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)

यहाँ एकल क्वेरी पर विस्तार है:

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

और यहाँ जॉय के लिए प्रदर्शन है:

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                     

इस पर मदद एक बहुत सराहना की जाएगी। :)

संपादित करें:

मुझे असंगत परिणाम मिल रहा है। यदि मैं उदाहरण के लिए Convert_tz निकालता हूं और संघ के बाहर टाइमजोन प्राप्त करने का प्रयास करता हूं तो मुझे बहुत तेज परिणाम मिलते हैं, लेकिन यदि मैं परिणाम का नाम बदल देता हूं तो यह स्वचालित रूप से उसी अंडरपरफॉर्मेंट क्वेरी में नीचे चला जाता है:

SELECT
    *,
    GetCarrierTimezone(carrier_id) timezone
FROM
(

इसमें 0.374 का समय लगता है

SELECT
    *,
    GetCarrierTimezone(carrier_id)
FROM
(

जबकि यह 0.078 लेता है (ज्यादातर db से मेरी मशीन के लिए अंतराल) ।।


सबसे सरल यह होगा कि उन्हें अलग से चलाया जाए और आवेदन में परिणामों को संयोजित किया जाए।
ypercube y

हाय @ypercube, कि मेरे मन को पार कर गया :) लेकिन ऐसा करने के लिए और उस कोड को बनाए रखने के लिए इतना बदसूरत। इसके अलावा मैं अभी भी php में परिणाम सॉर्ट करने के लिए है।

मेरा मतलब था कि वांछित प्रकार के साथ 2 प्रश्नों को चलाना। फिर आपको केवल php (कोई छँटाई) में विलय करने की आवश्यकता है।
ypercube y

1
छँटाई रैखिक नहीं है। क्वेरी 1 का परिणाम क्वेरी 2 के परिणामों के बीच में हो सकता है
आयोजित किया गया

1
मुझे नहीं लगता कि @ypercube मान रहा है कि परिणाम ओवरलैप नहीं हैं: 'मर्ज' php में लागू करने के लिए एक प्रकार से बहुत सस्ता / आसान है। यदि संभव हो तो एसक्यूएल में समस्या को ठीक करना एक बेहतर समाधान होगा :)
जैक ने कहा कि topanswers.xyz का प्रयास करें

जवाबों:


1

मुझे उम्मीद है कि आपके द्वारा वहां होने वाले आदेश के कारण ऐसा होगा।

UNION के पहले भाग में इसे आज़माएँ:

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

और यह दूसरे भाग में:

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

और फिर के ORDER BYसाथ बदलें

ORDER BY alertFoo

दूसरे शब्दों में, द्वारा क्रम में IF की आवश्यकता को हटा दें।


हाय थॉमस, सबसे पहले आपको अपने रिप्ले के लिए धन्यवाद। जैसा कि मैंने पिछले पोस्ट में कहा था कि यह कुछ समय पहले तय किया गया था। बात यह है कि मुझे अलर्ट 1 और अलर्ट 2 के बीच अंतर की आवश्यकता है। किसी भी मामले में आदेश जॉइन के परिणाम पर किया जाता है न कि जॉइन पर। क्वेरी के धीमेपन को सही ठहराने के लिए वे सभी परिणाम नहीं थे।
जार्ज

0

बहुत ही इसी तरह के मामले में, मैंने mysql की प्रक्रिया सूची से 'कॉपी टेम्प टू टेबल' (नकल क्या? मुझे नहीं पता) के बहुत बुरे व्यवहार पर ध्यान दिया। मुझे लगता है कि mysql ने क्वेरी करने के लिए एक 'सर्वश्रेष्ठ दृष्टिकोण' का प्रलोभन दिया, लेकिन इस मामले में असफल रहा, इसलिए कोड का उपयोग करके 2-क्वेरी परिणामों को ठीक किया।


हाय realtebo, इनपुट के लिए धन्यवाद। यह अब थोड़ा पुराना है, लेकिन मुझे जो असंगतता याद है, वह इसलिए थी क्योंकि कुछ लोग कैसे mysql कुछ परिणामों को कैच कर रहे थे और कुछ को नहीं। अंततः मैंने क्वेरी को और अधिक कुशल तरीके से फिर से बनाया, विशेष रूप से उन मूल्यों पर नज़र रखने के द्वारा जिन्हें मैंने एक अलग तालिका में आवश्यक किया जिससे सूचकांक अधिक कुशल हो गया।
13:54

0

यूनियन एसक्यूएल के धीमे चलने का मुख्य कारण यह है कि एक यूनियन माइक्सल्ड को आंतरिक अस्थायी तालिका बनाने का कारण बनता है। यह केवल UNION ALL के लिए एक तालिका बनाता है और एक UNIST DISTINCT के लिए अनुक्रमणिका (डुप्लिकेट को निकालने के लिए) के साथ एक तालिका है।

उम्मीद है की यह मदद करेगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.