Google ngrams को डेटाबेस में कैसे स्टोर करें?


9

मैंने कुछ दिनों पहले गूगल वनग्राम डाउनलोड किया और यह पहले से ही बड़ी मात्रा में डेटा है। मैंने 10 पैकेजों में से पहला mysql में डाला और अब मेरे पास 47 मिलियन रिकॉर्ड डेटाबेस है।

मैं सोच रहा हूं कि किसी एक डेटाबेस में Google ngrams को कैसे स्टोर करना चाहिए। मेरा मतलब है, यदि आप वनग्राम का उपयोग नहीं कर रहे हैं, लेकिन उदाहरण के लिए ट्वोग्राम्स या थ्रीग्राम्स की मात्रा बहुत बड़ी होगी। क्या मैं एक डेटाबेस में 500 मिलियन रिकॉर्ड संग्रहीत कर सकता हूं और इसके साथ काम कर सकता हूं या क्या मुझे इसे अलग-अलग तालिकाओं में विभाजित करना चाहिए?

कितने रिकॉर्ड के बाद किसी को विभाजित करना चाहिए और किसी को इसे कैसे विभाजित करना चाहिए (यह देखते हुए कि टोमोग्राम में 100 फाइलें हैं और इस तरह लगभग 5 बिलियन रिकॉर्ड हैं)? क्या यह MySQL क्षैतिज विभाजन का उपयोग करने या किसी के स्वयं विभाजन का निर्माण करने के लिए अनुशंसित है (उदाहरण के लिए शब्द के पहले चरित्र => twograms_a)।

जवाबों:


4

बहुत सारे बदलाव हुए जब मुझे अपना पहला उत्तर देना होगा तो मैं इसे शुरू कर दूंगा !!!

USE test
DROP TABLE IF EXISTS ngram_key;
DROP TABLE IF EXISTS ngram_rec;
DROP TABLE IF EXISTS ngram_blk;
CREATE TABLE ngram_key
(
    NGRAM_ID UNSIGNED BIGINT NOT NULL AUTO_INCREMENT,
    NGRAM VARCHAR(64) NOT NULL,
    PRIMARY KEY (NGRAM),
    KEY (NGRAM_ID)
) ENGINE=MyISAM ROW_FORMAT=FIXED PARTITION BY KEY(NGRAM) PARTITIONS 256;
CREATE TABLE ngram_rec
(
    NGRAM_ID UNSIGNED BIGINT NOT NULL,
    YR SMALLINT NOT NULL,
    MC SMALLINT NOT NULL,
    PC SMALLINT NOT NULL,
    VC SMALLINT NOT NULL,
    PRIMARY KEY (NGRAM_ID,YR)
) ENGINE=MyISAM ROW_FORMAT=FIXED;
CREATE TABLE ngram_blk
(
    NGRAM VARCHAR(64) NOT NULL,
    YR SMALLINT NOT NULL,
    MC SMALLINT NOT NULL,
    PC SMALLINT NOT NULL,
    VC SMALLINT NOT NULL
) ENGINE=BLACKHOLE;
DELIMITER $$
CREATE TRIGGER populate_ngram AFTER INSERT ON ngram_blk FOR EACH ROW
BEGIN
    DECLARE NEW_ID BIGINT;

    INSERT IGNORE INTO ngram_key (NGRAM) VALUES (NEW.NGRAM);
    SELECT NGRAM_ID INTO NEW_ID FROM ngram_key WHERE NGRAM=NEW.NGRAM;
    INSERT IGNORE INTO ngram_rec VALUES (NEW_ID,NEW.YR,NEW.MC,NEW.PC,NEW.VC);
END; $$
DELIMITER ;
INSERT INTO ngram_blk VALUES
('rolando',1965,31,29,85),
('pamela',1971,33,21,86),
('dominique',1996,30,18,87),
('diamond',1998,13,28,88),
('rolando edwards',1965,31,29,85),
('pamela edwards',1971,33,21,86),
('dominique edwards',1996,30,18,87),
('diamond edwards',1998,13,28,88),
('rolando angel edwards',1965,31,29,85),
('pamela claricia edwards',1971,33,21,86),
('dominique sharlisee edwards',1996,30,18,87),
('diamond ashley edwards',1998,13,28,88);
UPDATE ngram_rec SET yr=yr+1,mc=mc+30,pc=pc+30,vc=vc+30;
INSERT INTO ngram_blk VALUES
('rolando',1965,31,29,85),
('pamela',1971,33,21,86),
('dominique',1996,30,18,87),
('diamond',1998,13,28,88),
('rolando edwards',1965,31,29,85),
('pamela edwards',1971,33,21,86),
('dominique edwards',1996,30,18,87),
('diamond edwards',1998,13,28,88),
('rolando angel edwards',1965,31,29,85),
('pamela claricia edwards',1971,33,21,86),
('dominique sharlisee edwards',1996,30,18,87),
('diamond ashley edwards',1998,13,28,88);
UPDATE ngram_rec SET yr=yr+1,mc=mc+30,pc=pc+30;
INSERT INTO ngram_blk VALUES
('rolando',1965,31,29,85),
('pamela',1971,33,21,86),
('dominique',1996,30,18,87),
('diamond',1998,13,28,88),
('rolando edwards',1965,31,29,85),
('pamela edwards',1971,33,21,86),
('dominique edwards',1996,30,18,87),
('diamond edwards',1998,13,28,88),
('rolando angel edwards',1965,31,29,85),
('pamela claricia edwards',1971,33,21,86),
('dominique sharlisee edwards',1996,30,18,87),
('diamond ashley edwards',1998,13,28,88);
UPDATE ngram_rec SET yr=yr+1,mc=mc+30;
SELECT * FROM ngram_key;
SELECT * FROM ngram_rec;
SELECT A.ngram NGram,B.yr Year,B.mc Matches,B.pc Pages,B.vc Volumes FROM 
ngram_key A,ngram_rec B
WHERE A.ngram='rolando angel edwards'
AND A.ngram_id=B.ngram_id;

वर्ष की जानकारी के लिए बहुत छोटी टेबल लेकिन मूलग्राम को संरक्षित करने के लिए बहुत बड़ी चाबियां। मैंने परीक्षण डेटा की मात्रा भी बढ़ाई। आप इसे सीधे MySQL में काट और पेस्ट कर सकते हैं।

चेतावनी

बस ROW_FORMAT को हटा दें और यह डायनामिक हो जाता है और ngram_key टेबल को बहुत छोटा कर देता है।


डिस्कस्पेस मेट्रिक्स

nrgram_rec में ngram_id के
लिए 8 बाइट्स प्रति पंक्ति 17 बाइट्स हैं (अधिकतम अहस्ताक्षरित मान 18446744073709551615 [2 ^ 64 - 1])
4 बाइट्स के लिए 8 बाइट्स (2 बाइट्स प्रत्येक
1 बाइट MyISAM आंतरिक हटाएं ध्वज

Ngram_rec = 10 बाइट्स (8 (ngram_id) + 2 (yr) के लिए अनुक्रमणिका प्रविष्टि

47 मिलियन पंक्तियाँ X 17 बाइट्स प्रति पंक्ति = 0799 मिलियन बाइट्स = 761.98577 MB
47 मिलियन पंक्तियाँ X 12 बाइट्स प्रति पंक्ति = 0564 मिलियन बाइट्स = 537.85231 MB
47 मिलियन पंक्तियाँ X 29 बाइट्स प्रति पंक्ति = 13 मिलियन मिलियन बाइट्स = 1.269393 GB

5 बिलियन पंक्तियाँ X 17 बाइट्स प्रति पंक्ति = 085 बिलियन बाइट्स = 079.1624 GB
5 बिलियन रोएँ X 12 बाइट्स प्रति पंक्ति = 060 बिलियन बाइट्स = 055.8793 GB
5 बिलियन पंक्तियाँ X 29 बाइट्स प्रति पंक्ति = 145 बिलियन बाइट्स = 135.0417 GB


ngram_key में ngram के लिए 73 बाइट्स 64 बाइट्स हैं (ROW_FORMAT = FIXED set varchar to char) 8 बाइट्स के लिए ngram_id 1 बाइट MyISAM आंतरिक डिलीट फ्लैग

Ngram_key = 64 बाइट्स + 8 बाइट्स = 72 बाइट्स के लिए 2 सूचकांक प्रविष्टियाँ

47 मिलियन पंक्तियों X 073 बाइट्स प्रति पंक्ति = 3431 मिलियन बाइट्स = 3.1954 GB
47 मिलियन पंक्तियों X 072 बाइट्स प्रति पंक्ति = 3384 मिलियन बाइट्स = 3.1515 GB
47 मिलियन पंक्तियों X 145 बाइट्स प्रति पंक्ति = 6815 मिलियन बाइट्स = 6.3469 GB

5 बिलियन पंक्तियाँ X 073 बाइट्स प्रति पंक्ति = 365 बिलियन बाइट्स = 339.9327 GB
5 बिलियन रोएँ X 072 बाइट्स प्रति पंक्ति = 360 बिलियन बाइट्स = 335.2761 GB
5 बिलियन पंक्तियाँ X 145 बाइट्स प्रति पंक्ति = 725 बिलियन बाइट्स = 675.2088 GB


दो महान जवाब के लिए धन्यवाद। मैं उत्सुक हूँ, टेबल को आबाद करने के लिए इस ब्लैकहोल + ट्रिगर विधि का उपयोग करने का क्या कारण है?
Dolan Antenucci

ब्लैकहोल orignal ngram स्वीकार करता है। ट्रिगर एक स्वच्छ INSERT IGNORE तंत्र बनाता है जिससे ngram को auto_increment मान से विभाजित किया जा सके।
रोलैंडमाइसीडीडीबीए

3

यहाँ एक बहुत बढ़िया सुझाव है

सभी वर्णों को 32-वर्ण MD5 कुंजियों में कनवर्ट करें

यह तालिका किसी भी आकार (255 वर्ण तक), 1-ग्राम, 2-ग्राम, आदि के सभी हिस्सों को पकड़ेगी।

use test
DROP TABLE ngram_node;
DROP TABLE ngram_blackhole;
CREATE TABLE ngram_node
(
  NGRAM_KEY  CHAR(32) NOT NULL,
  NGRAM_YEAR SMALLINT NOT NULL,
  M_COUNT    SMALLINT NOT NULL,
  P_COUNT    SMALLINT NOT NULL,
  V_COUNT    SMALLINT NOT NULL,
  PRIMARY KEY   (NGRAM_KEY,NGRAM_YEAR)
) ENGINE=MyISAM
PARTITION BY KEY(NGRAM_KEY)
PARTITIONS 256;
CREATE TABLE ngram_blackhole
(
  NGRAM      VARCHAR(255) NOT NULL,
  NGRAM_YEAR SMALLINT NOT NULL,
  M_COUNT    SMALLINT NOT NULL,
  P_COUNT    SMALLINT NOT NULL,
  V_COUNT    SMALLINT NOT NULL
) ENGINE=BLACKHOLE;
DELIMITER $$
CREATE TRIGGER populate_ngram AFTER INSERT ON ngram_blackhole FOR EACH ROW
BEGIN
    INSERT INTO ngram_node VALUES (MD5(NEW.NGRAM),NEW.NGRAM_YEAR,NEW.M_COUNT,NEW.P_COUNT,NEW.V_COUNT);
END; $$
DELIMITER ;
INSERT INTO ngram_blackhole VALUES
('rolando',1965,31,29,85),
('pamela',1971,33,21,86),
('dominique',1996,30,18,87),
('diamond',1998,13,28,88),
('rolando edwards',1965,31,29,85),
('pamela edwards',1971,33,21,86),
('dominique edwards',1996,30,18,87),
('diamond edwards',1998,13,28,88),
('rolando angel edwards',1965,31,29,85),
('pamela claricia edwards',1971,33,21,86),
('dominique sharlisee edwards',1996,30,18,87),
('diamond ashley edwards',1998,13,28,88);
SELECT * FROM ngram_node;

मेरे द्वारा 256 विभाजनों को चुनने का कारण इस तथ्य से है कि MD5 फ़ंक्शन 16 अलग-अलग वर्ण (सभी हेक्साडेसिमल अंक) लौटाता है। पहले दो बाइट्स 16 X 16, 256 हैं।

यहाँ मेरा विंडोज 7 डेस्कटॉप पर MySQL 5.5.11 में परिणाम था

mysql> use test
Database changed
mysql> DROP TABLE ngram_node;
Query OK, 0 rows affected (0.22 sec)

mysql> DROP TABLE ngram_blackhole;
Query OK, 0 rows affected (0.11 sec)

mysql> CREATE TABLE ngram_node
    -> (
    ->   NGRAM_KEY  CHAR(32) NOT NULL,
    ->   NGRAM_YEAR SMALLINT NOT NULL,
    ->   M_COUNT    SMALLINT NOT NULL,
    ->   P_COUNT    SMALLINT NOT NULL,
    ->   V_COUNT    SMALLINT NOT NULL,
    ->   PRIMARY KEY    (NGRAM_KEY,NGRAM_YEAR)
    -> ) ENGINE=MyISAM
    -> PARTITION BY KEY(NGRAM_KEY)
    -> PARTITIONS 256;
Query OK, 0 rows affected (0.36 sec)

mysql> CREATE TABLE ngram_blackhole
    -> (
    ->   NGRAM      VARCHAR(255) NOT NULL,
    ->   NGRAM_YEAR SMALLINT NOT NULL,
    ->   M_COUNT    SMALLINT NOT NULL,
    ->   P_COUNT    SMALLINT NOT NULL,
    ->   V_COUNT    SMALLINT NOT NULL
    -> ) ENGINE=BLACKHOLE;
Query OK, 0 rows affected (0.11 sec)

mysql> DELIMITER $$
mysql> CREATE TRIGGER populate_ngram AFTER INSERT ON ngram_blackhole FOR EACH ROW
    -> BEGIN
    ->  INSERT INTO ngram_node VALUES (MD5(NEW.NGRAM),NEW.NGRAM_YEAR,NEW.M_COUNT,NEW.P_COUNT,NEW.V_COUNT);
    -> END; $$
Query OK, 0 rows affected (0.05 sec)

mysql> DELIMITER ;
mysql> INSERT INTO ngram_blackhole VALUES
    -> ('rolando',1965,31,29,85),
    -> ('pamela',1971,33,21,86),
    -> ('dominique',1996,30,18,87),
    -> ('diamond',1998,13,28,88),
    -> ('rolando edwards',1965,31,29,85),
    -> ('pamela edwards',1971,33,21,86),
    -> ('dominique edwards',1996,30,18,87),
    -> ('diamond edwards',1998,13,28,88),
    -> ('rolando angel edwards',1965,31,29,85),
    -> ('pamela claricia edwards',1971,33,21,86),
    -> ('dominique sharlisee edwards',1996,30,18,87),
    -> ('diamond ashley edwards',1998,13,28,88);
Query OK, 12 rows affected (0.18 sec)
Records: 12  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM ngram_node;
+----------------------------------+------------+---------+---------+---------+
| NGRAM_KEY                        | NGRAM_YEAR | M_COUNT | P_COUNT | V_COUNT |
+----------------------------------+------------+---------+---------+---------+
| 2ca237192aaac3b3a20ce0649351b395 |       1996 |      30 |      18 |      87 |
| 6f7fd3368170c562604f62fb4e92056d |       1965 |      31 |      29 |      85 |
| fb201333fef377917be714dabd3776d9 |       1971 |      33 |      21 |      86 |
| 4f79e21800ed6e30be4d1cb597f910c6 |       1971 |      33 |      21 |      86 |
| 9068e0de9f3fd674d4fa7cbc626e5888 |       1998 |      13 |      28 |      88 |
| 8a18abe90f2612827dc3a215fd1905d3 |       1965 |      31 |      29 |      85 |
| be60b431a46fcc7bf5ee4f7712993e3b |       1996 |      30 |      18 |      87 |
| c8adc38aa00759488b1d759aa8f91725 |       1996 |      30 |      18 |      87 |
| e80d4ab77eb18a4ca350157fd487d7e2 |       1965 |      31 |      29 |      85 |
| 669ffc150d1f875819183addfc842cab |       1971 |      33 |      21 |      86 |
| b685323e9de65080f733b53b2305da6e |       1998 |      13 |      28 |      88 |
| 75c6f03161d020201000414cd1501f9f |       1998 |      13 |      28 |      88 |
+----------------------------------+------------+---------+---------+---------+
12 rows in set (0.00 sec)

mysql>

कृपया ध्यान दें कि मैंने 1-ग्राम, 2-ग्राम और 3-ग्राम को एक ही तालिका में लोड किया है, लेकिन आपके पास कोई सुराग नहीं है कि एमडी 5 किस नोड से संबंधित है। इस प्रकार, सभी एनग्राम इस एक तालिका में पीछे हट सकते हैं। बस ngram_blackhole तालिका में सम्मिलित करना याद रखें और बाकी आपके लिए किया जाता है।

आपको ngram के MD5 () का उपयोग करके ngram_node तालिका को क्वेरी करना चाहिए चाहे कोई भी ngram।

mysql> select * from ngram_node where ngram_key=MD5('rolando edwards');
+----------------------------------+------------+---------+---------+---------+
| NGRAM_KEY                        | NGRAM_YEAR | M_COUNT | P_COUNT | V_COUNT |
+----------------------------------+------------+---------+---------+---------+
| 6f7fd3368170c562604f62fb4e92056d |       1965 |      31 |      29 |      85 |
+----------------------------------+------------+---------+---------+---------+
1 row in set (0.05 sec)

यदि आप 1-ग्राम, 2-ग्राम और 3-ग्राम को अलग-अलग रिपॉजिटरी में अलग करना चाहते हैं, तो दूसरी टेबल में डालने के लिए ब्लैकहोल टेबल पर एक और टेबल, एक और ब्लैकहोल टेबल और एक और ट्रिगर बनाएं।

इसके अलावा, यदि आपके ngrams 255 से अधिक हैं (यदि आप 7-ग्राम या 8-ग्राम कर रहे हैं) तो ngram_blackhole तालिका में NGRAM कॉलम के VARCHAR आकार को बढ़ाएं।

कोशिश करो !!!

अपडेट करें

प्रश्न में, यह कहा गया था कि 47 मिलियन पंक्तियों को mysql में लोड किया गया था। मेरी सुझाई गई तालिका लेआउट के लिए, कृपया निम्नलिखित पर ध्यान दें:

ngram_node प्रति पंक्ति 41 बाइट्स है:
संख्या के लिए NGRAM_KEY 8 के लिए 32 (प्रत्येक SMALLINT के लिए 2)
1 आंतरिक MyISAM DELETED ध्वज के लिए

प्रत्येक प्राथमिक कुंजी इंडेक्स प्रविष्टि
NGRAM_YEAR के लिए NGRAM_KEY
2 के लिए 34 बाइट्स 32 होगी

47 मिलियन पंक्तियाँ एक्स 41 बाइट्स प्रति पंक्ति = 1.927 बिलियन बाइट्स, लगभग 1.79466 जीबी।
47 मिलियन पंक्तियाँ X 34 बाइट्स प्रति सूचकांक प्रविष्टि = 1.598 बिलियन बाइट्स, लगभग 1.48825 GB।
MyISAM तालिका की खपत कुल मिलाकर 3.28291 GB होनी चाहिए।

प्रश्न में 5 बिलियन पंक्तियों को लोड करने का भी उल्लेख किया गया है।

5 बिलियन रो X 41 बाइट्स प्रति रो = 205 बिलियन बाइट्स, लगभग 190.9211 GB।
5 बिलियन रो X 34 बाइट्स प्रति इंडेक्स एंट्री = 170 बिलियन बाइट्स, लगभग 158.3248 GB।
MyISAM टेबल की खपत कुल मिलाकर 349.2459 GB होनी चाहिए।

कृपया ध्यान दें कि निरंतर आकार की प्राथमिक कुंजी के कारण MyISAM तालिका में उपयोग किए गए स्थान की वृद्धि दर रैखिक है। अब आप इसके आधार पर डिस्क स्थान के लिए कुछ योजना बना सकते हैं।


1
मैंने अपने उत्तर के बारे में सोचा और मेरे पास एक और सुझाव है, ताकि कम डिस्क स्थान का उपयोग किया जाए। मैं इसे सोमवार को संबोधित करूँगा !!! आपका सप्ताहांत शुभ हो।
रोलैंडमाइसीडीडीबीए
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.