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

डेटाबेस से यादृच्छिक पंक्तियों को कैसे प्रतिध्वनित करें?

यहां प्रस्तुत दो समाधान। ये दोनों प्रस्तावित समाधान mysql-only हैं और उपभोक्ता के रूप में किसी भी प्रोग्रामिंग भाषा द्वारा उपयोग किए जा सकते हैं। इसके लिए PHP बेतहाशा बहुत धीमी होगी, लेकिन यह इसका उपभोक्ता हो सकता है।

तेज़ समाधान :मैं अधिक उन्नत प्रोग्रामिंग तकनीकों के साथ एक सेकंड के लगभग 2 दसवें हिस्से में 19 मिलियन पंक्तियों की तालिका से 1000 यादृच्छिक पंक्तियाँ ला सकता हूँ।

धीमा समाधान :गैर-शक्ति प्रोग्रामिंग तकनीकों के साथ इसमें लगभग 15 सेकंड लगते हैं।

वैसे दोनों यहां देखे गए डेटा जेनरेशन का उपयोग करते हैं कि मैंने लिखा। तो वह मेरी छोटी स्कीमा है। मैं इसका उपयोग करता हूं, TWO . के साथ जारी रखें जब तक मेरे पास 19M पंक्तियाँ नहीं हैं, तब तक वहाँ पर और अधिक आत्म-आवेषण देखे गए। इसलिए मैं इसे दोबारा नहीं दिखाने जा रहा हूं। लेकिन उन 19M पंक्तियों को प्राप्त करने के लिए, वह देखें, और उनमें से 2 और सम्मिलित करें, और आपके पास 19M पंक्तियाँ हैं।

पहले धीमा संस्करण

सबसे पहले, धीमी विधि।

select id,thing from ratings order by rand() limit 1000;

यह 15 सेकंड में 1000 पंक्तियाँ लौटाता है।

तेज़ समाधान

यह वर्णन करने के लिए थोड़ा और जटिल है। इसका सार यह है कि आप अपनी यादृच्छिक संख्याओं की पूर्व-गणना करते हैं और एक in clause . उत्पन्न करते हैं समाप्त यादृच्छिक संख्याओं का, अल्पविराम द्वारा अलग किया गया, और कोष्ठक की एक जोड़ी के साथ लपेटा गया।

यह (1,2,3,4) . जैसा दिखेगा लेकिन इसमें 1000 नंबर होंगे।

और आप उन्हें स्टोर करते हैं, और एक बार उनका इस्तेमाल करते हैं। क्रिप्टोग्राफी के लिए वन टाइम पैड की तरह। ठीक है, एक महान सादृश्य नहीं है, लेकिन मुझे आशा है कि आपको वह बात मिल जाएगी।

इसे in . के अंत के रूप में सोचें क्लॉज, और एक टेक्स्ट कॉलम (एक ब्लॉब की तरह) में संग्रहीत।

दुनिया में कोई ऐसा क्यों करना चाहेगा? क्योंकि RNG (यादृच्छिक संख्या जनरेटर) निषेधात्मक रूप से धीमे हैं। लेकिन कुछ मशीनों के साथ उन्हें उत्पन्न करने के लिए हजारों अपेक्षाकृत जल्दी क्रैंक करने में सक्षम हो सकते हैं। वैसे (और आप इसे मेरे तथाकथित परिशिष्टों की संरचना में देखेंगे, मैं कैप्चर करता हूं कि एक पंक्ति उत्पन्न करने में कितना समय लगता है। MySQL के साथ लगभग 1 सेकंड। लेकिन सी #, पीएचपी, जावा, कुछ भी इसे एक साथ रख सकता है। बिंदु यह नहीं है कि आप इसे कैसे एक साथ रखते हैं, बल्कि, जब आप इसे चाहते हैं तो आपके पास यह है।

यह रणनीति, इसकी लंबी और छोटी है, जब इसे एक ऐसी पंक्ति लाने के साथ जोड़ा जाता है जिसे यादृच्छिक सूची के रूप में उपयोग नहीं किया गया है, इसे उपयोग के रूप में चिह्नित किया गया है, और कॉल जारी करना जैसे

select id,thing from ratings where id in (a,b,c,d,e, ... )

और इन क्लॉज में 1000 नंबर हैं, परिणाम आधे सेकेंड से भी कम समय में उपलब्ध हैं। mysql CBO (लागत आधारित अनुकूलक) को प्रभावी ढंग से नियोजित करने के बजाय इसे PK अनुक्रमणिका में शामिल होने जैसा व्यवहार करता है।

मैं इसे सारांश रूप में छोड़ता हूं, क्योंकि यह व्यवहार में थोड़ा जटिल है, लेकिन इसमें संभावित रूप से निम्नलिखित कण शामिल हैं

  • पूर्व-गणना की गई यादृच्छिक संख्याओं वाली तालिका (परिशिष्ट A)
  • एक mysql ईवेंट रणनीति बनाएं (परिशिष्ट B)
  • एक संग्रहित प्रक्रिया जो कर्मचारियों को एक तैयार विवरण (परिशिष्ट सी)
  • आरएनजी in प्रदर्शित करने के लिए एक mysql-only संग्रहीत खरीद किक के लिए क्लॉज (परिशिष्ट डी)

परिशिष्ट A

पूर्व-गणना यादृच्छिक संख्याओं वाली तालिका

create table randomsToUse
(   -- create a table of 1000 random numbers to use
    -- format will be like a long "(a,b,c,d,e, ...)" string

    -- pre-computed random numbers, fetched upon needed for use

    id int auto_increment primary key,
    used int not null,  -- 0 = not used yet, 1= used
    dtStartCreate datetime not null, -- next two lines to eyeball time spent generating this row
    dtEndCreate datetime not null,
    dtUsed datetime null, -- when was it used
    txtInString text not null -- here is your in clause ending like (a,b,c,d,e, ... )
    -- this may only have about 5000 rows and garbage cleaned
    -- so maybe choose one or two more indexes, such as composites
);

परिशिष्ट B

इसे पुस्तक में न बदलने के हित में, मेरा उत्तर देखें यहां आवर्ती MySQL ईवेंट चलाने के लिए एक तंत्र के लिए। यह परिशिष्ट ए में देखी गई तालिका के रखरखाव को परिशिष्ट डी में देखी गई तकनीकों और अन्य विचारों का उपयोग करके चलाएगा जिन्हें आप सपना देखना चाहते हैं। जैसे कि पंक्तियों का पुन:उपयोग, संग्रह करना, हटाना, जो भी हो।

परिशिष्ट C

संग्रहीत प्रक्रिया बस मुझे 1000 यादृच्छिक पंक्तियाँ प्राप्त करने के लिए।

DROP PROCEDURE if exists showARandomChunk;
DELIMITER $$
CREATE PROCEDURE showARandomChunk
(
)
BEGIN
  DECLARE i int;
  DECLARE txtInClause text;

  -- select now() into dtBegin;

  select id,txtInString into i,txtInClause from randomsToUse where used=0 order by id limit 1;
  -- select txtInClause as sOut; -- used for debugging

  -- if I run this following statement, it is 19.9 seconds on my Dell laptop
  -- with 19M rows
  -- select * from ratings order by rand() limit 1000; -- 19 seconds

  -- however, if I run the following "Prepared Statement", if takes 2 tenths of a second
  -- for 1000 rows

  set @s1=concat("select * from ratings where id in ",txtInClause);

  PREPARE stmt1 FROM @s1;
  EXECUTE stmt1; -- execute the puppy and give me 1000 rows
  DEALLOCATE PREPARE stmt1;
END
$$
DELIMITER ;

परिशिष्ट D

परिशिष्ट बी अवधारणा के साथ जोड़ा जा सकता है। हालाँकि आप इसे करना चाहते हैं। लेकिन यह आपको यह देखने के लिए कुछ छोड़ देता है कि MySQL चीजों के आरएनजी पक्ष पर यह सब कैसे कर सकता है। वैसे, पैरामीटर 1 और 2 के क्रमशः 1000 और 19M होने के कारण, यह मेरी मशीन पर 800 ms लेता है।

यह रूटीन किसी भी भाषा में लिखा जा सकता है जैसा कि शुरुआत में बताया गया है।

drop procedure if exists createARandomInString;
DELIMITER $$
create procedure createARandomInString
(   nHowMany int, -- how many numbers to you want
    nMaxNum int -- max of any one number
)
BEGIN
    DECLARE dtBegin datetime;
    DECLARE dtEnd datetime;
    DECLARE i int;
    DECLARE txtInClause text;
    select now() into dtBegin;

    set i=1;
    set txtInClause="(";
    WHILE i<nHowMany DO
        set txtInClause=concat(txtInClause,floor(rand()*nMaxNum)+1,", "); -- extra space good due to viewing in text editor
        set i=i+1;
    END WHILE;
    set txtInClause=concat(txtInClause,floor(rand()*nMaxNum)+1,")");
    -- select txtInClause as myOutput; -- used for debugging
    select now() into dtEnd;

    -- insert a row, that has not been used yet
    insert randomsToUse(used,dtStartCreate,dtEndCreate,dtUsed,txtInString) values 
       (0,dtBegin,dtEnd,null,txtInClause);
END
$$
DELIMITER ;

उपरोक्त संग्रहीत खरीद को कैसे कॉल करें:

call createARandomInString(1000,18000000);

यह ऊपर वर्णित अनुसार लिपटे हुए 1000 नंबरों में से 1 पंक्ति को उत्पन्न और सहेजता है। बड़ी संख्या, 1 से 18M

एक त्वरित उदाहरण के रूप में, यदि कोई संग्रहीत खरीद को संशोधित करता है, तो नीचे की रेखा को अन-रेम करें जो कहता है कि "डिबगिंग के लिए उपयोग किया जाता है", और इसे अंतिम पंक्ति के रूप में, संग्रहीत प्रो में चलता है, और इसे चलाएं:

call createARandomInString(4,18000000);

... 18M तक 4 यादृच्छिक संख्याएँ उत्पन्न करने के लिए, परिणाम कुछ इस तरह दिख सकते हैं

+-------------------------------------+
| myOutput                            |
+-------------------------------------+
| (2857561,5076608,16810360,14821977) |
+-------------------------------------+

परिशिष्ट E

वास्तविकता की जांच। ये कुछ हद तक उन्नत तकनीकें हैं और मैं इन पर किसी को पढ़ा नहीं सकता। लेकिन मैं उन्हें वैसे भी साझा करना चाहता था। लेकिन मैं इसे नहीं सिखा सकता। बार-बार।



  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 ट्रिगर किसी फ़ील्ड को id के मान पर अपडेट करने के लिए

  2. परिणाम से दिनांक कैसे प्राप्त करेंसेट

  3. मैं तैयार पीडीओ स्टेटमेंट का उपयोग करके ORDER BY params कैसे सेट करूं?

  4. Linux में "MySQL ERROR 1819 (HY000):" को कैसे ठीक करें

  5. GROUP BY का उपयोग करते समय अनुपलब्ध (शून्य-गिनती) पंक्तियों सहित