Como posso acelerar esta consulta abaixo? Tenho uma tabela ~grande com url_meta
90 milhões de registros, 38 GB de dados, 6 GB de Ãndice
O ID exclusivo principal de cada linha é url_hash
(um md5 truncado para 16 caracteres)
Então criei um grande Ãndice de texto completo chamado url_meta_index
, contendo estas colunas:
- tÃtulo_url
- url_descrição
- palavras-chave url
- url_paragrafos
A tabela também contém uma coluna indexada chamadaurl_total_links_in
- Se eu selecionar apenas as URLs com muitos links, o processo será muito rápido e, o mais importante, há apenas 240 linhas com mais de 1.000 links:
SELECT * FROM url_meta WHERE url_total_links_in > 1000
240 rows in set (0.01 sec)
Mas se eu pesquisar no Ãndice de texto grande DEPOIS da mesma consulta (selecionando as mesmas linhas acima) , isso demora uma eternidade:
mysql> SELECT * FROM url_meta WHERE url_total_links_in > 1000 AND match(url_title, url_description, url_keywords, url_paragraphs) against('computer store' IN BOOLEAN MODE) LIMIT 500; 10 rows in set (4 min 4.94 sec)
Eu esperava match against
que a segunda parte olhasse apenas os 240 registros que encontrou por url_total_links_in > 1000
, não é assim que funciona ? Pelo longo tempo de consulta, acho que ele olha todos os 90 milhões de registros.
Por PHP, posso selecionar as 240 linhas na primeira consulta e, em seguida, fazer um loop sobre essas poucas linhas para "comparar" com o texto mostrado na segunda consulta. Mas como posso fazer isso pelo MySQL?
Ajudaria se eu ... incluÃsse o id de linha exclusivo ( url_hash
) no Ãndice de texto multicoluna grande url_meta_index
? Ou ajuda se eu adicionar a coluna url_total_links_in
ao mesmo Ãndice de texto multicoluna url_meta_index
? Algum outro operador MySQL que ajudaria neste caso? Ou alguma variável MySQL que seria relevante neste caso?
Edição posterior, incluindo mais detalhes:
DESCRIBE url_meta;
+--------------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------------+--------------+------+-----+---------+-------+
| url_hash | char(16) | NO | PRI | NULL | |
| url_sharding | char(2) | YES | MUL | NULL | |
| url | varchar(512) | NO | | NULL | |
| url_title | varchar(128) | YES | MUL | NULL | |
| url_description | text | YES | | NULL | |
| url_keywords | varchar(128) | YES | | NULL | |
| url_paragraphs | mediumtext | YES | | NULL | |
| url_total_links_in | smallint | NO | MUL | 0 | |
| url_meta_date | int | NO | | 0 | |
| url_misc | tinyint | YES | | NULL | |
+--------------------+--------------+------+-----+---------+-------+
EXPLAIN ANALYZE SELECT * FROM url_meta WHERE url_total_links_in > 1000 AND match(url_title, url_description, url_keywords, url_paragraphs) against('computer store' IN BOOLEAN MODE) LIMIT 500;
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| EXPLAIN |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| -> Limit: 500 row(s) (cost=0.40 rows=0.05) (actual time=2582.991..21198.806 rows=10 loops=1)
-> Filter: ((url_meta.url_total_links_in > 1000) and (match url_meta.url_title,url_meta.url_description,url_meta.url_keywords,url_meta.url_paragraphs against ('computer store' in boolean mode))) (cost=0.40 rows=0.05) (actual time=2582.991..21198.800 rows=10 loops=1)
-> Full-text index search on url_meta using url_meta_index (url_title='computer store') (cost=0.40 rows=1) (actual time=312.284..21096.609 rows=1247864 loops=1)
|
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (23.36 sec)
SHOW INDEX FROM url_meta;
+----------+------------+--------------------+--------------+--------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+----------+------------+--------------------+--------------+--------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| url_meta | 0 | PRIMARY | 1 | url_hash | A | 81358144 | NULL | NULL | | BTREE | | | YES | NULL |
| url_meta | 1 | url_total_links_in | 1 | url_total_links_in | A | 2790 | NULL | NULL | | BTREE | | | YES | NULL |
| url_meta | 1 | url_sharding | 1 | url_sharding | A | 1590 | NULL | NULL | YES | BTREE | | | YES | NULL |
| url_meta | 1 | url_meta_index | 1 | url_title | NULL | 81358147 | NULL | NULL | YES | FULLTEXT | | | YES | NULL |
| url_meta | 1 | url_meta_index | 2 | url_description | NULL | 81358147 | NULL | NULL | YES | FULLTEXT | | | YES | NULL |
| url_meta | 1 | url_meta_index | 3 | url_keywords | NULL | 81358147 | NULL | NULL | YES | FULLTEXT | | | YES | NULL |
| url_meta | 1 | url_meta_index | 4 | url_paragraphs | NULL | 81358147 | NULL | NULL | YES | FULLTEXT | | | YES | NULL |
+----------+------------+--------------------+--------------+--------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
7 rows in set (0.00 sec)
A única maneira que o MySQL pode fazer
MATCH
é fazê-lo primeiro . Isso levou a 1.247.864 linhas. O restoWHERE
reduziu para muito poucas linhas.