Il y avait tellement de changements que je devais apporter à ma première réponse, je commence celle-ci !!!
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;
Des tableaux beaucoup plus petits pour les informations sur l'année mais des touches beaucoup plus grandes pour conserver le schéma d'origine. J'ai également augmenté la quantité de données de test. Vous pouvez couper et coller cela directement dans MySQL.
CAVEAT
Supprimez simplement ROW_FORMAT et cela devient dynamique et compressez les tables ngram_key beaucoup plus petites.
Mesures DiskSpace
nrgram_rec a 17 octets par ligne
8 octets pour ngram_id (valeur maximale non signée 18446744073709551615 [2 ^ 64 - 1])
8 octets pour 4 petits caractères (2 octets chacun)
1 octet indicateur de suppression interne MyISAM
Entrée d'index pour ngram_rec = 10 octets (8 (ngram_id) + 2 (an))
47 millions de lignes X 17 octets par ligne = 0799 millions d'octets = 761,98577 Mo
47 millions de lignes X 12 octets par ligne = 0564 millions d'octets = 537,85231 Mo
47 millions de lignes X 29 octets par ligne = 1363 millions d'octets = 1,269393 Go
5 milliards de lignes X 17 octets par ligne = 085 milliards d'octets = 079,1624 Go
5 milliards de lignes X 12 octets par ligne = 060 milliard d'octets = 055,8793 Go
5 milliards de lignes X 29 octets par ligne = 145 milliards d'octets = 135,0417 Go
ngram_key a 73 octets 64 octets pour ngram (ROW_FORMAT = FIXED définit varchar sur char) 8 octets pour ngram_id 1 octet Drapeau de suppression interne MyISAM
2 entrées d'index pour ngram_key = 64 octets + 8 octets = 72 octets
47 millions de lignes X 073 octets par ligne = 3431 millions d'octets = 3,1954 Go
47 millions de lignes X 072 octets par ligne = 3384 millions d'octets = 3,1515 Go
47 millions de lignes X 145 octets par ligne = 6815 millions d'octets = 6,3469 Go
5 milliards de lignes X 073 octets par ligne = 365 milliards d'octets = 339,9327 Go
5 milliards de lignes X 072 octets par ligne = 360 milliards d'octets = 335,2761 Go
5 milliards de lignes X 145 octets par ligne = 725 milliards d'octets = 675,2088 Go
Voici une suggestion assez folle
Convertissez tous les ngrams en touches MD5 à 32 caractères
Ce tableau contiendra tous les ngrammes de n'importe quelle taille (jusqu'à 255 caractères), 1 gramme, 2 grammes, etc.
La raison pour laquelle j'ai choisi 256 partitions provient du fait que la fonction MD5 renvoie 16 caractères distincts (tous des chiffres hexadécimaux). Les deux premiers octets sont 16 X 16, 256.
Voici le résultat dans MySQL 5.5.11 sur mon bureau Windows 7
Veuillez noter que j'ai chargé 1 gramme, 2 grammes et 3 grammes dans la même table mais vous n'avez aucune idée de quel MD5 appartient à quel ngram. Ainsi, tous les ngrammes peuvent être intégrés dans cette seule table. N'oubliez pas d'insérer dans la table ngram_blackhole et le reste est fait pour vous.
Vous devez interroger la table ngram_node à l'aide du MD5 () du ngram, quel que soit le ngram.
Si vous souhaitez séparer 1 gramme, 2 grammes et 3 grammes dans des référentiels distincts, créez simplement une autre table, une autre table de trou noir et un autre déclencheur sur la table de trou noir pour l'insérer dans l'autre table.
De plus, si vos ngrams dépassent 255 (si vous faites 7 grammes ou 8 grammes), augmentez simplement la taille VARCHAR de la colonne NGRAM dans la table ngram_blackhole.
Essaie !!!
MISE À JOUR
Dans la question, il a été déclaré que 47 millions de lignes ont été chargées dans mysql. Pour ma disposition de table suggérée, veuillez noter ce qui suit:
ngram_node est de 41 octets par ligne: 32 pour NGRAM_KEY
8 pour les nombres (2 pour chaque SMALLINT)
1 pour l'indicateur MyISAM DELETED interne
Chaque entrée d'index de clé primaire serait de 34 octets
32 pour NGRAM_KEY
2 pour NGRAM_YEAR
47 millions de lignes X 41 octets par ligne = 1,927 milliard d'octets, soit environ 1,79466 Go.
47 millions de lignes X 34 octets par entrée d'index = 1,598 milliard d'octets, environ 1,48825 Go.
La consommation de la table MyISAM devrait être d'environ un total combiné de 3,28291 Go.
La question mentionnait également le chargement de 5 milliards de lignes.
5 milliards de lignes X 41 octets par ligne = 205 milliards d'octets, soit environ 190,9211 Go.
5 milliards de lignes X 34 octets par entrée d'index = 170 milliards d'octets, soit environ 158,3248 Go.
La consommation de la table MyISAM devrait être d'environ un total combiné de 349.2459 Go.
Veuillez noter que le taux de croissance de l'espace utilisé dans la table MyISAM est linéaire en raison de la clé primaire de taille constante. Vous pouvez désormais planifier l'espace disque en fonction de cela.
la source