दिलचस्प पोस्ट
एंड्रॉइड: वेबवेव में पाठ चयन अक्षम करें हस्ताक्षरित पूर्णांक को एक अहस्ताक्षरित लंबे समय तक परिवर्तित करने का सर्वोत्तम तरीका? इकाई फ़्रेमवर्क 4.1 व्युत्क्रम प्रॉपर्टी विशेषता और विदेशी की लूप और IF स्टेटमेंट को गठबंधन करने का पायथनिक तरीका जावा में स्ट्रिंग सरणी को ऑब्जेक्ट सरणी कैसे परिवर्तित करें मैं एक asp.net MVC नियंत्रक कार्रवाई पैरामीटर के रूप में एक सरणी कैसे स्वीकार करूँ? एसक्यूएल की तरह और एक साथ में उपयोग करना एसक्यूएल नेटवर्क इंटरफेसेस, त्रुटि: 26 – सर्वर / इंस्टेंस निर्दिष्ट करने में त्रुटि एकत्रीकरण के बाद वापस मूल दस्तावेज़ वापस कैसे प्राप्त करें सापेक्ष पथ और जावास्क्रिप्ट में पूर्ण पथ के बीच का अंतर बाइंडिंग लिस्ट <T> में डाटाग्रीड दृश्य में WinForm JavaFX "स्थान आवश्यक है।" भले ही यह एक ही पैकेज में है Event.stopPropagation और event.preventDefault के बीच क्या अंतर है? अड़चन के साथ, मैं कैसे दबाव की एक श्रृंखला को "दबाव" से पहले एक में "संक्षिप्त" कर सकता हूँ? एलिमेंट-वार 2 सूचियों के अलावा?

उन मानों का चयन करें जो अलग-अलग पंक्तियों पर विभिन्न स्थितियों को पूरा करते हैं?

यह एक बहुत ही बुनियादी क्वेरी है जो मैं समझ नहीं पा रहा हूं ….

मान लीजिए मेरे पास इस तरह एक दो स्तंभ तालिका है:

userid | roleid --------|-------- 1 | 1 1 | 2 1 | 3 2 | 1 

मुझे 1, 2 और 3 के सभी विशिष्ट यूजर आईडी मिलना है। उपर्युक्त उदाहरण का प्रयोग करना, केवल एक ही परिणाम है जो मैं roleids चाहता हूं userid 1. मैं यह कैसे कर सकता हूँ?

वेब के समाधान से एकत्रित समाधान "उन मानों का चयन करें जो अलग-अलग पंक्तियों पर विभिन्न स्थितियों को पूरा करते हैं?"

 SELECT userid FROM UserRole WHERE roleid IN (1, 2, 3) GROUP BY userid HAVING COUNT(DISTINCT roleid) = 3; 

इसे पढ़ने वाले किसी के लिए: मेरा जवाब सरल और सीधा है, और 'स्वीकृत' स्थिति प्राप्त कर ली है, लेकिन कृपया @ सेलेस द्वारा दिए गए उत्तर को पढ़ें। इसमें बेहतर प्रदर्शन है


ज़ोर देना ज़ोर से सोच रहा है, @ सेलेस्ट्रेट्स द्वारा वर्णित आत्म-सम्मिलित लिखने का दूसरा तरीका है:

 SELECT t1.userid FROM userrole t1 JOIN userrole t2 ON t1.userid = t2.userid JOIN userrole t3 ON t2.userid = t3.userid WHERE (t1.roleid, t2.roleid, t3.roleid) = (1, 2, 3); 

यह आपके लिए पढ़ने के लिए आसान हो सकता है, और MySQL ट्यूपल्स की समान तुलना करता है। MySQL यह भी जानता है कि इस प्रश्न के लिए अनुक्रमित को समझने के लिए उपयोग कैसे करें। बस इसे EXPLAIN माध्यम से चलाएं और सभी तीन तालिकाओं के लिए नोट्स में "सूचकांक का उपयोग" देखें, जिसका मतलब है कि यह सूचकांक पढ़ रहा है और डेटा पंक्तियों को भी छूने की ज़रूरत नहीं है

मैंने इस क्वेरी को मेरी मैकबुक पर MySQL 5.1.48 का उपयोग करते हुए 2.1 मिलियन पंक्तियों (पोस्टटैग्स के लिए स्टैक ओवरफ़्लो जुलाई डेटा डंप) पर चलाया, और इसने परिणाम को 1.08 सेकंड में वापस कर दिया। innodb_buffer_pool_size को आवंटित पर्याप्त स्मृति के साथ एक सभ्य सर्वर पर, यह और भी तेज होनी चाहिए।

ठीक है, मुझे इसके बारे में नीचे बताया गया, इसलिए मैंने इसका परीक्षण करने का फैसला किया:

 CREATE TABLE userrole ( userid INT, roleid INT, PRIMARY KEY (userid, roleid) ); CREATE INDEX ON userrole (roleid); 

इसे चलाओ:

 <?php ini_set('max_execution_time', 120); // takes over a minute to insert 500k+ records $start = microtime(true); echo "<pre>\n"; mysql_connect('localhost', 'scratch', 'scratch'); if (mysql_error()) { echo "Connect error: " . mysql_error() . "\n"; } mysql_select_db('scratch'); if (mysql_error()) { echo "Selct DB error: " . mysql_error() . "\n"; } $users = 200000; $count = 0; for ($i=1; $i<=$users; $i++) { $roles = rand(1, 4); $available = range(1, 5); for ($j=0; $j<$roles; $j++) { $extract = array_splice($available, rand(0, sizeof($available)-1), 1); $id = $extract[0]; query("INSERT INTO userrole (userid, roleid) VALUES ($i, $id)"); $count++; } } $stop = microtime(true); $duration = $stop - $start; $insert = $duration / $count; echo "$count users added.\n"; echo "Program ran for $duration seconds.\n"; echo "Insert time $insert seconds.\n"; echo "</pre>\n"; function query($str) { mysql_query($str); if (mysql_error()) { echo "$str: " . mysql_error() . "\n"; } } ?> 

आउटपुट:

 499872 users added. Program ran for 56.5513510704 seconds. Insert time 0.000113131663847 seconds. 

यह 500,000 यादृच्छिक उपयोगकर्ता भूमिका संयोजन जोड़ता है और लगभग 25,000 चयनित मानदंडों से मेल खाते हैं।

पहला प्रश्न:

 SELECT userid FROM userrole WHERE roleid IN (1, 2, 3) GROUP by userid HAVING COUNT(1) = 3 

प्रश्न समय: 0.312s

 SELECT t1.userid FROM userrole t1 JOIN userrole t2 ON t1.userid = t2.userid AND t2.roleid = 2 JOIN userrole t3 ON t2.userid = t3.userid AND t3.roleid = 3 AND t1.roleid = 1 

प्रश्न समय: 0.016

ये सही है। मेरे द्वारा प्रस्तावित होने वाले संस्करण में कुल संस्करण की तुलना में बीस गुना तेजी है।

खेद है, लेकिन मैं इसे वास्तविक दुनिया में रहने और काम करने के लिए करता हूं और वास्तविक दुनिया में हम एसक्यूएल का परीक्षण करते हैं और परिणाम स्वयं के लिए कहते हैं।

इसका कारण स्पष्ट होना चाहिए। कुल क्वेरी तालिका के आकार के साथ लागत में स्केल करेगी हर पंक्ति को HAVING खंड के माध्यम से संसाधित, एकत्रित और फ़िल्टर्ड (या नहीं) किया जाता है संयुक्त संस्करण में (एक इंडेक्स का प्रयोग करना) किसी दी गई भूमिका के आधार पर उपयोगकर्ताओं का सबसेट चुनना होगा, फिर दूसरी भूमिका के खिलाफ सबसेट जांचें और आखिरकार तीसरे रोल के साथ वह सबसेट। प्रत्येक चयन ( संबंधपरक बीजगणित शब्दों में) एक तेजी से छोटे उपसमुच्चय पर काम करता है। इससे आप निष्कर्ष निकाल सकते हैं:

मैचों की कम घटना के साथ जुड़ने के संस्करण का प्रदर्शन भी बेहतर होता है।

यदि केवल 500 उपयोगकर्ता (ऊपर दिए गए 500k नमूने में से) में तीनों भूमिकाओं की थी, तो शामिल होने का संस्करण काफी तेज़ हो जाएगा। कुल संस्करण नहीं होगा (और कोई भी प्रदर्शन सुधार 25k के बजाय 500 उपयोगकर्ताओं को ट्रांसपोर्ट करने का एक परिणाम है, जो भी शामिल होने के संस्करण को स्पष्ट रूप से भी मिलता है)।

मैं यह भी देखने के लिए उत्सुक था कि कैसे एक वास्तविक डेटाबेस (यानी ओरेकल) इस के साथ सौदा होगा। इसलिए मैंने मूल रूप से ओरेकल एक्सई पर एक ही अभ्यास को दोहराया (पिछले संस्करण से एक ही विंडोज़ XP डेस्कटॉप मशीन पर MySQL के रूप में चल रहा है) और परिणाम लगभग समान हैं।

जुड़ने लगते हैं पर frowned हो, लेकिन जैसा कि मैंने दिखाया है, सकल प्रश्न तीव्रता के एक आदेश हो सकता है धीमी

अद्यतन: कुछ व्यापक परीक्षण के बाद, तस्वीर अधिक जटिल है और उत्तर आपके डेटा, आपके डेटाबेस और अन्य कारकों पर निर्भर करेगा। कहानी की नैतिक परीक्षा, परीक्षा, परीक्षा है।

उपयोगकर्ता आईडी मानते हुए, भूमिका एक अद्वितीय सूचकांक में समाहित होती है (अर्थात इसमें 2 रिकॉर्ड नहीं हो सकते हैं, जहां यूजरआइड = x और रोलिड = 1

 select count(*), userid from t where roleid in (1,2,3) group by userid having count(*) = 3 

ऐसा करने का क्लासिक तरीका यह है कि यह एक संबंधपरक विभाजन की समस्या के रूप में इलाज करे।

अंग्रेजी में: उन उपयोगकर्ताओं का चयन करें जिनके लिए वांछित रोलिड मानों में से कोई भी गायब नहीं है।

मुझे लगता है कि आपके पास एक उपयोगकर्ता तालिका है जिसमें उपयोगकर्ता रोल तालिका संदर्भित करती है, और मुझे लगता है कि वांछित भूमिका निष्ठा तालिका में हैं:

 create table RoleGroup( roleid int not null, primary key(roleid) ) insert into RoleGroup values (1); insert into RoleGroup values (2); insert into RoleGroup values (3); 

मैं यह भी मानूंगा कि सभी संबंधित कॉलम उतना योग्य नहीं हैं, इसलिए इनके साथ कोई आश्चर्य नहीं है या नहीं। यहां एक एसक्यूएल क्वेरी है जो उपरोक्त अंग्रेजी को व्यक्त करती है:

 select userid from Users as U where not exists ( select * from RoleGroup as G where not exists ( select R.roleid from UserRole as R where R.roleid = G.roleid and R.userid = U.userid ) ); 

इसे लिखने का दूसरा तरीका यह है

 select userid from Users as U where not exists ( select * from RoleGroup as G where G.roleid not in ( select R.roleid from UserRole as R where R.userid = U.userid ) ); 

इंडेक्स, प्लेटफ़ॉर्म, डेटा आदि के आधार पर यह कुशल हो सकता है या न खत्म हो सकता है। "रिलेशनल डिवीजन" के लिए वेब पर खोजें और आपको बहुत कुछ मिलेगा।

 select userid from userrole where userid = 1 intersect select userid from userrole where userid = 2 intersect select userid from userrole where userid = 3 

क्या इस समस्या का समाधान नहीं होगा? ठेठ रिलेशनल डीबीएस पर यह कितना अच्छा समाधान है? क्या ऑप्टिमाइज़र से स्वयं का अनुकूलन करेगा?

अगर आपको किसी भी तरह की सामान्यता की आवश्यकता है (अलग-अलग 3-भूमिका संयोजन या विभिन्न एन-रोल संयोजन) … मैं आपको अपनी भूमिकाओं के लिए थोड़ी मास्किंग सिस्टम का उपयोग करने का सुझाव देता हूं और अपने प्रश्नों को करने के लिए bitwise ऑपरेटरों का उपयोग करता हूं …