2010-04-25 12 views
5
mysql> EXPLAIN SELECT * FROM urls ORDER BY RAND() LIMIT 1; 
+----+-------------+-------+------+---------------+------+---------+------+-------+---------------------------------+ 
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra       | 
+----+-------------+-------+------+---------------+------+---------+------+-------+---------------------------------+ 
| 1 | SIMPLE  | urls | ALL | NULL   | NULL | NULL | NULL | 62228 | Using temporary; Using filesort | 
+----+-------------+-------+------+---------------+------+---------+------+-------+---------------------------------+ 

उपर्युक्त कुशल के रूप में योग्य नहीं है, मुझे इसे ठीक से कैसे करना चाहिए?मैं MySQL में एक यादृच्छिक रिकॉर्ड कुशलतापूर्वक कैसे चुनूं?

अद्यतन

समाधान जवाब में बताया गया का उपयोग कर अभी भी मदद नहीं करता है लगता है:

mysql> explain SELECT * 
    -> FROM (
    ->   SELECT @cnt := COUNT(*) + 1, 
    ->     @lim := 10 
    ->   FROM urls 
    ->  ) vars 
    -> STRAIGHT_JOIN 
    ->   (
    ->   SELECT r.*, 
    ->     @lim := @lim - 1 
    ->   FROM urls r 
    ->   WHERE (@cnt := @cnt - 1) 
    ->     AND RAND(20090301) < @lim/@cnt 
    ->  ) i; 
+----+-------------+------------+--------+---------------+------+---------+------+-------+------------------------------+ 
| id | select_type | table  | type | possible_keys | key | key_len | ref | rows | Extra      | 
+----+-------------+------------+--------+---------------+------+---------+------+-------+------------------------------+ 
| 1 | PRIMARY  | <derived2> | system | NULL   | NULL | NULL | NULL |  1 |        | 
| 1 | PRIMARY  | <derived3> | ALL | NULL   | NULL | NULL | NULL | 10 |        | 
| 3 | DERIVED  | r   | ALL | NULL   | NULL | NULL | NULL | 62228 | Using where     | 
| 2 | DERIVED  | NULL  | NULL | NULL   | NULL | NULL | NULL | NULL | Select tables optimized away | 
+----+-------------+------------+--------+---------------+------+---------+------+-------+------------------------------+ 

उत्तर

4

Quassnoi एक तरह से बिना प्रदर्शन यादृच्छिक पर पंक्तियों का चयन के बारे में post लिखा है। उनका उदाहरण यादृच्छिक रूप से 10 पंक्तियों का चयन करता है, लेकिन आप इसे केवल एक पंक्ति चुनने के लिए अनुकूलित कर सकते हैं।

यदि आप वास्तव में तेजी से चाहते हैं तो आप एक अनुमान का उपयोग कर सकते हैं जो पूरी तरह से समान नहीं होगा या कभी-कभी पंक्ति को वापस करने में विफल रहेगा।

तुम भी Bill Karwin's post से जल्दी से एक यादृच्छिक पंक्ति का चयन करने के लिए एक संग्रहीत प्रक्रिया का उपयोग कर सकते हैं:

SET @r := (SELECT ROUND(RAND() * (SELECT COUNT(*) FROM mytable))); 
SET @sql := CONCAT('SELECT * FROM mytable LIMIT ', @r, ', 1'); 
PREPARE stmt1 FROM @sql; 
EXECUTE stmt1; 

ध्यान दें कि यह InnoDB से MyISAM में बहुत तेजी से चलेंगे क्योंकि COUNT (*) महंगा InnoDB में लेकिन लगभग तुरंत है माईसाम में

+0

लगता है कि यह मेरे मामले में काम नहीं कर रहा है। – user198729

+0

@ user198729: ऊपर दिए गए कोड को देखते हुए आप 10 से 1 तक 'lim' को बदलना भूल गए हैं। शायद मैंने इसे स्पष्ट नहीं किया है। –

+0

इससे कोई फर्क नहीं पड़ता, 10 से 1 को बदलने के बाद भी वही है। समझाओ आउटपुट की तीसरी पंक्ति पर ध्यान दें। – user198729

0

ठीक है, अगर आप कुछ तर्क को एप्लिकेशन लेयर में ले जा सकते हैं (और मैंने आपके प्रश्न को गलत समझा नहीं है), तो आपको केवल अपने आवेदन में यादृच्छिक आईडी उत्पन्न करना है और फिर उस कुंजी द्वारा पहचाने गए एक रिकॉर्ड के लिए सरल चयन करना है । आपको केवल इतना जानने की जरूरत है कि रिकॉर्ड की गिनती है। ओह, और अगर वह कुंजी हटा दी गई थी, तो अगला प्राप्त करें।

संबंधित मुद्दे