Havia tantas mudanças que eu teria que fazer na minha primeira resposta, eu começo essa !!!
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;
Tabelas muito menores para informações do ano, mas teclas muito maiores para preservar o ngram original. Também aumentei a quantidade de dados de teste. Você pode recortar e colar isso diretamente no MySQL.
EMBARGO
Simplesmente remova o ROW_FORMAT e ele se tornará manímico e comprima as tabelas ngram_key muito menores.
Métricas do DiskSpace
nrgram_rec possui 17 bytes por linha,
8 bytes para ngram_id (valor máximo não assinado 18446744073709551615 [2 ^ 64 - 1])
8 bytes para 4 smallints (2 bytes cada)
flag de exclusão interna MyISAM de 1 byte
Entrada de índice para ngram_rec = 10 bytes (8 (ngram_id) + 2 (ano))
47 milhões de linhas X 17 bytes por linha = 0799 milhões de bytes = 761.98577 MB
47 milhões de linhas X 12 bytes por linha = 0564 milhões de bytes = 537,85231 MB
47 milhões de linhas X 29 bytes por linha = 1363 milhões de bytes = 1.269393 GB
5 bilhões de linhas X 17 bytes por linha = 085 bilhões de bytes = 079.1624 GB
5 bilhões de linhas X 12 bytes por linha = 060 bilhões de bytes = 055.8793 GB
5 bilhões de linhas X 29 bytes por linha = 145 bilhões de bytes = 135.0417 GB
ngram_key possui 73 bytes 64 bytes para ngram (ROW_FORMAT = FIXO define varchar como char) 8 bytes para ngram_id 1 sinalizador interno de exclusão do MyISAM de 1 byte
2 Entradas de índice para ngram_key = 64 bytes + 8 bytes = 72 bytes
47 milhões de linhas X 073 bytes por linha = 3431 milhões de bytes = 3,1954 GB
47 milhões de linhas X 072 bytes por linha = 3384 milhões de bytes = 3,1515 GB
47 milhões de linhas X 145 bytes por linha = 6815 milhões de bytes = 6,3469 GB
5 bilhões de linhas X 073 bytes por linha = 365 bilhões de bytes = 339.9327 GB
5 bilhões de linhas X 072 bytes por linha = 360 bilhões de bytes = 335.2761 GB
5 bilhões de linhas X 145 bytes por linha = 725 bilhões de bytes = 675.2088 GB
Aqui está uma sugestão bastante selvagem
Converta todos os ngrams em chaves MD5 de 32 caracteres
Esta tabela conterá todos os ngrams de qualquer tamanho (até 255 caracteres), 1 grama, 2 gramas, etc.
A razão pela qual escolhi 256 partições decorre do fato de a função MD5 retornar 16 caracteres distintos (todos os dígitos hexadecimais). Os primeiros dois bytes são 16 x 16, 256.
Aqui estão os resultados do MySQL 5.5.11 no meu Windows 7 Desktop
Observe que eu carreguei 1, 2 e 3 gramas na mesma tabela, mas você não tem idéia de qual MD5 pertence a qual ngram. Assim, todos os ngrams podem se adaptar a essa tabela. Lembre-se de inserir na tabela ngram_blackhole e o resto é feito para você.
Você deve consultar a tabela ngram_node usando o MD5 () do ngram, independentemente de qual ngram.
Se você deseja separar 1 grama, 2 gramas e 3 gramas em repositórios separados, basta criar outra tabela, outra tabela de buraco negro e outro gatilho na tabela de buraco negro para inserir na outra tabela.
Além disso, se seus ngrams forem maiores que 255 (se você estiver fazendo 7 ou 8 gramas), apenas aumente o tamanho VARCHAR da coluna NGRAM na tabela ngram_blackhole.
De uma chance !!!
ATUALIZAR
Na questão, foi declarado que 47 milhões de linhas foram carregadas no mysql. Para o meu layout de tabela sugerido, observe o seguinte:
ngram_node é 41 bytes por linha: 32 para NGRAM_KEY
8 para os números (2 para cada SMALLINT)
1 para o sinalizador interno MyISAM DELETED
Cada entrada de índice de chave primária teria 34 bytes
32 para NGRAM_KEY
2 para NGRAM_YEAR
47 milhões de linhas X 41 bytes por linha = 1,927 bilhão de bytes, cerca de 1,79466 GB.
47 milhões de linhas X 34 bytes por entrada de índice = 1,598 bilhão de bytes, cerca de 1,48825 GB.
O consumo da tabela MyISAM deve ser de um total combinado de 3,28291 GB.
A pergunta também mencionou o carregamento de 5 bilhões de linhas.
5 bilhões de linhas X 41 bytes por linha = 205 bilhões de bytes, cerca de 190,9211 GB.
5 bilhões de linhas X 34 bytes por entrada de índice = 170 bilhões de bytes, cerca de 158,3248 GB.
O consumo da tabela MyISAM deve ser de um total combinado de 349,2459 GB.
Observe que a taxa de crescimento do espaço usado na tabela MyISAM é linear devido à chave primária de tamanho constante. Agora você pode planejar o espaço em disco com base nisso.
fonte