2011-09-17 13 views
9

के साथ यादृच्छिक रिकॉर्ड प्राप्त करें मुझे आश्चर्य है कि समूह से सदस्यों की यादृच्छिक संख्या कैसे प्राप्त करें, लेकिन मुझे नहीं पता कि ऐसा करने का सबसे अच्छा तरीका क्या है, और मुझे लगता है कि ORDER BY RAND() सबसे अच्छा विकल्प नहीं है, क्योंकि समूह समूह कर सकता है 100,000 से अधिक सदस्य हैं, इस प्रकार की क्वेरी निष्पादित करना बहुत धीमा हो सकता है।Doctrine

मैं एसक्यूएल का उपयोग कर बनाने के लिए इस तरह से मिल गया, लेकिन मैं कैसे DQL में एक ही बात करने के लिए पता नहीं है: How can i optimize MySQL's ORDER BY RAND() function?

+1

संभावित डुप्लिकेट [सिद्धांत के साथ यादृच्छिक रूप से कैसे चुनें] (http://stackoverflow.com/questions/10762538/how-to-select-randomly-with-doctrine) –

उत्तर

0

मैं() "कुशलता" से रेंड द्वारा ऑर्डर करने के लिए किसी भी तरह से के बारे में पता नहीं कर रहा हूँ सिद्धांत। आपकी स्थिति में, सबसे अच्छी बात यह है कि प्राथमिक कुंजी पहले प्राप्त करने के लिए, इन चाबियों को घुमाएं और फिर इन्हें एक आईएन कथन के भीतर उपयोग करें।

आप पहली क्वेरी से चाबियाँ (एक सबसेट) डालने के लिए एक कैशिंग परत भी जोड़ सकते हैं, खासकर यदि आपके पास कई रिकॉर्ड हैं, इसलिए प्रत्येक बार कुंजी पर क्वेरी दोहराने से बचें।

4

आप देशी एसक्यूएल क्वेरी के माध्यम से एन यादृच्छिक अभिलेखों के आईडी को कुशलतापूर्वक पुनर्प्राप्त करने के लिए प्राप्त क्वेरी का उपयोग कर सकते हैं, फिर डीक्यूएल का उपयोग करके WHERE IN(...) के माध्यम से वस्तुओं को लाने के लिए एक सिद्धांत क्वेरी करें।

उदाहरण:

// fetch $randomIds via native sql query using $em->getConnection()->... methods 
// or from a memory based cache 

$qb = $em->createQueryBuilder('u'); 

$em->createQuery(' 
    SELECT u 
    FROM Entity\User 
    WHERE ' . $qb->expr()->in('u.id', $randomIds) . ' 
'); 

एक ही रणनीति लागू होता है अगर आप एक कैश से यादृच्छिक आईडी लाने (जैसे redis, हो सकता है का उपयोग कर SRANDMEMBER) - पहला, आईडी लाने फिर एक WHERE IN के माध्यम से इकाइयां नहीं लाई।

तुम बस सुनिश्चित करें कि आपके कैश की गई आईडी डेटाबेस के साथ सिंक में हैं (नष्ट आईडी डेटाबेस कैश आदि से और से हटा दिया जाता है) के रूप में इस

+0

मेरे पास एक अवलोकन है। '$ Em-> getConnection() -> ...' या '$ em-> createQuery ('... SQL क्वेरी ...') के माध्यम से देशी एसक्यूएल क्वेरी के माध्यम से आईडी को प्राप्त करना '' समान नहीं है आप? – JeanValjean

12

प्रदर्शन मैं आम तौर पर कर में कमी नहीं करने के लिए करना है:

//Retrieve the EntityManager first 
$em = $this->getEntityManager(); 

//Get the number of rows from your table 
$rows = $em->createQuery('SELECT COUNT(u.id) FROM AcmeUserBundle:User u')->getSingleScalarResult(); 

$offset = max(0, rand(0, $rows - $amount - 1)); 

//Get the first $amount users starting from a random point 
$query = $em->createQuery(' 
       SELECT DISTINCT u 
       FROM AcmeUserBundle:User u') 
->setMaxResults($amount) 
->setFirstResult($offset); 

$result = $query->getResult(); 
बेशक

, $amount उपयोगकर्ताओं आपत्ति आप पुनः प्राप्त कर रहे हैं लगातार (यानी i-वें (i + 1) वें, ..., (i + $amount) मई के), लेकिन आम तौर पर वहाँ की जरूरत है यादृच्छिक रूप से एक या दो इकाइयों को लेने की पूरी सूची नहीं। इसलिए, मुझे लगता है कि यह एक प्रभावी विकल्प है।

+0

आप एक कस्टम संख्यात्मक एफएन या DoctrineExtensions Lib का उपयोग [वैकल्पिक] (http://digitalfortress.tech/php/get-random-rows-in-doctrine/) के रूप में भी कर सकते हैं। –