Mysql
 sql >> डेटाबेस >  >> RDS >> Mysql

बहुत विशिष्ट MySQL क्वेरी जिसे मैं सुधारना चाहता हूँ

यदि आपके पास created . के साथ एक अनुक्रमणिका है अग्रणी कॉलम के रूप में, MySQL एक रिवर्स स्कैन करने में सक्षम हो सकता है। यदि आपके पास 24 घंटे की अवधि है जिसमें कोई ईवेंट नहीं है, तो आप उस पंक्ति को वापस कर सकते हैं जो उस अवधि से नहीं है। यह सुनिश्चित करने के लिए कि आपको उस अवधि में एक पंक्ति मिल रही है, आपको वास्तव में created पर एक निचला बाउंड शामिल करना होगा कॉलम भी, कुछ इस तरह:

SELECT * FROM `eventos`
 WHERE ... 
   AND `created` <  FROM_UNIXTIME( {$timestamp} )
   AND `created` >= DATE_ADD(FROM_UNIXTIME( {$timestamp} ),INTERVAL -24 HOUR)
 ORDER BY `created` DESC
 LIMIT 1

मुझे लगता है कि यहां प्रदर्शन की बड़ी कुंजी created . के साथ एक अनुक्रमणिका है WHERE क्लॉज में संदर्भित अन्य सभी (या अधिकतर) कॉलम के साथ प्रमुख कॉलम के रूप में, और यह सुनिश्चित करना कि आपकी क्वेरी द्वारा इंडेक्स का उपयोग किया जाता है।

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

SELECT * FROM `eventos`
 WHERE ... 
   AND `created` <  DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL  0*{$nsecs} SECOND)
   AND `created` >= DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL -1*{$nsecs} SECOND)
 ORDER BY `created` DESC
 LIMIT 1

आपके कोड से, ऐसा लगता है कि 24-घंटे की अवधि एक मनमाना समय पर बंधी हुई है ... यदि समय फ़ंक्शन वापस आता है उदा। 1341580800 ('2012-07-06 13:20'), तो आपके सभी दस पीरियड किसी दिए गए दिन 13:20 से अगले दिन 13:20 तक होंगे।

(नोट:सुनिश्चित करें कि यदि आपका पैरामीटर एक यूनिक्स टाइमस्टैम्प पूर्णांक है, तो डेटाबेस द्वारा इसकी सही व्याख्या की जा रही है।)

एक ही प्रश्न में दस पंक्तियों को खींचना अधिक कुशल हो सकता है। यदि इस बात की कोई गारंटी है कि 'टाइमस्टैम्प' अद्वितीय है, तो ऐसी क्वेरी तैयार करना संभव है, लेकिन क्वेरी टेक्स्ट आपके पास अभी जो है उससे कहीं अधिक जटिल होगा। हम प्रत्येक अवधि के भीतर MAX(timestamp_) प्राप्त करने में गड़बड़ी कर सकते हैं, और फिर पंक्ति प्राप्त करने के लिए उसमें वापस शामिल हो सकते हैं... लेकिन यह वास्तव में गड़बड़ होने वाला है।

अगर मैं सभी दस पंक्तियों को खींचने की कोशिश करने जा रहा था तो शायद मैं UNION ALL के साथ जाने का प्रयास करूंगा दृष्टिकोण, बहुत सुंदर नहीं है, लेकिन कम से कम इसे ट्यून किया जा सकता है।

SELECT p0.*
  FROM ( SELECT * FROM `eventos` WHERE ... 
            AND `created` <  DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL  0*24 HOUR)
            AND `created` >= DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL -1*24 HOUR)
          ORDER BY `created` DESC LIMIT 1
       ) p0 
 UNION ALL           
SELECT p1.*
  FROM ( SELECT * FROM `eventos` WHERE ... 
            AND `created` <  DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL -1*24 HOUR)
            AND `created` >= DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL -2*24 HOUR)
          ORDER BY `created` DESC LIMIT 1
       ) p1 
 UNION ALL           
SELECT p2.*
  FROM ( SELECT * FROM `eventos` WHERE ... 
            AND `created` <  DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL -2*24 HOUR)
            AND `created` >= DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL -3*24 HOUR)
          ORDER BY `created` DESC LIMIT 1
       ) p2 
 UNION ALL           
SELECT p3.*
  FROM ...

फिर, इसे एक तर्क के रूप में कई सेकंड में पारित करने के लिए सामान्यीकृत किया जा सकता है। HOUR को SECOND से बदलें, और '24' को एक बाइंड पैरामीटर से बदलें, जिसमें कई सेकंड हों।

यह काफी लंबा घुमावदार है, लेकिन इसे ठीक चलना चाहिए।

एक परिणाम सेट में इसे वापस लाने का एक और वास्तव में गन्दा और जटिल तरीका दस अवधियों के लिए अंतिम टाइमस्टैम्प प्राप्त करने के लिए एक इनलाइन दृश्य का उपयोग करना होगा, कुछ इस तरह:

     SELECT p.period_end
       FROM (SELECT DATE_ADD(t.t_,INTERVAL -1 * i.i_* {$nsecs} SECOND) AS period_end
               FROM (SELECT FROM_UNIXTIME( {$timestamp} ) AS t_) t
               JOIN (SELECT 0 AS i_
                     UNION ALL SELECT 1
                     UNION ALL SELECT 2
                     UNION ALL SELECT 3
                     UNION ALL SELECT 4
                     UNION ALL SELECT 5
                     UNION ALL SELECT 6
                     UNION ALL SELECT 7
                     UNION ALL SELECT 8
                     UNION ALL SELECT 9
                    ) i
            ) p

और फिर उसे अपनी टेबल में शामिल करें...

  ON `created` < p.period_end
 AND `created` >= DATE_ADD(p.period_end,INTERVAL -1 * {$nsecs} SECOND)

और प्रत्येक अवधि के लिए MAX(बनाया) वापस खींचो, समूह द्वारा p.period_end, उसे एक इनलाइन दृश्य में लपेटें।

और फिर प्रत्येक पंक्ति प्राप्त करने के लिए उसे वापस अपनी तालिका में शामिल करें।

लेकिन यह वास्तव में, वास्तव में गन्दा है, समझने में कठिन है, और जो आप पहले से कर रहे हैं उससे अधिक तेज़ (या अधिक कुशल) होने की संभावना नहीं है। आप जो सबसे अधिक सुधार कर सकते हैं, वह है आपके 9 प्रश्नों को चलाने में लगने वाला समय।



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. mysql php . से छवि प्राप्त करें

  2. पैकेज com.mysql.jdbc.PreparedStatement में क्या अंतर है; और java.sql.PreparedStatement?

  3. कोणीय लूप अपडेट नहीं हो रहा है

  4. क्यों mysqli_real_escape_string में पहले पैरामीटर के रूप में कनेक्शन ऑब्जेक्ट है

  5. वाक्पटु ORM / laravel . के साथ तैयार बयान