简体   繁体   English

即使使用索引,连接两个表 MySQL 也很慢

[英]Joining two tables MySQL is slow even with indexing

I have two tables:我有两个表:

The first one table1 is created on the fly (as the user submits data from a web server) and is usually ~50K rows.第一个table1是动态创建的(当用户从​​ Web 服务器提交数据时),通常是大约 50K 行。 The second table is a lookup table table2 and has ~10Mil rows.第二个表是一个查找表table2 ,有大约 10Mil 行。

I'm trying to join both tables on four columns as follows:我正在尝试将两个表连接到四列,如下所示:

SELECT t.id FROM table1 t 
JOIN table2 m
ON (t.name = m.name AND t.pos = m.pos AND t.ref = m.ref AND t.alt = m.alt);

I've indexed columns name (VARCHAR), pos (INT), ref (CHAR) and alt (CHAR) in table2 , but the query still takes way too long to complete.我在table2对列name (VARCHAR)、 pos (INT)、 ref (CHAR) 和alt (CHAR) 进行了索引,但查询仍然需要很长时间才能完成。

Any pointers on what could be going wrong here?关于这里可能出现什么问题的任何指示?

Thanks谢谢


Output of EXPLAIN : EXPLAIN输出:

id  select_type table   partitions  type    possible_keys   key key_len ref rows    filtered    Extra
1   SIMPLE  t1  NULL    ALL NULL    NULL    NULL    NULL    49329   100.00  Using where
1   SIMPLE  t2  NULL    ref table2_name,table2_pos,table2_ref,table2_alt    table2_name 32  my_db.t1.NAME   2488    0.00    Using index condition; Using where

Create a compound index on name, pos, ref, altname, pos, ref, alt上创建复合索引

like喜欢

INDEX theIndex (name,pos,ref, alt)

Also, 4 single indices will help a little bit - see http://dev.mysql.com/doc/refman/5.7/en/index-merge-optimization.html - but not as much as a compound index.此外,4 个单一索引会有所帮助 - 请参阅http://dev.mysql.com/doc/refman/5.7/en/index-merge-optimization.html - 但不如复合索引那么多。

Two things to try here:在这里尝试两件事:

  1. The first is the easiest -- change the order of your join clause to move the varchar column to the end.第一个是最简单的——更改 join 子句的顺序以将 varchar 列移到末尾。

SELECT t.id FROM table1 t JOIN table2 m ON (t.pos = m.pos AND t.ref = m.ref AND t.alt = m.alt AND t.name = m.name); SELECT t.id FROM table1 t JOIN table2 m ON (t.pos = m.pos AND t.ref = m.ref AND t.alt = m.alt AND t.name = m.name);

  1. This is a little more work, but add a new computed column that generates a numeric hash based on the 4 columns.这需要做更多的工作,但添加一个新的计算列,该列基于 4 列生成数字哈希。 Remove the indexes on pos, ref, alt and name and add a new index to the the hash column.删除 pos、ref、alt 和 name 上的索引,并向哈希列添加新索引。 Then include the hash column in your join clause.然后在您的连接子句中包含哈希列。

SELECT t.id FROM table1 t JOIN table2 m ON (t.hash = m.hash AND t.pos = m.pos AND t.ref = m.ref AND t.alt = m.alt AND t.name = m.name); SELECT t.id FROM table1 t JOIN table2 m ON (t.hash = m.hash AND t.pos = m.pos AND t.ref = m.ref AND t.alt = m.alt AND t.name = m.姓名);

Edit: Without looking at your database and the query execution plan, it's hard to troubleshoot this, but my guess is that MySQL is having a hard time joining on the VARCHAR column.编辑:不查看您的数据库和查询执行计划,很难解决这个问题,但我的猜测是 MySQL 很难加入 VARCHAR 列。 Can you update your question with the results of你能用结果更新你的问题吗

EXPLAIN SELECT t.id FROM table1 t JOIN table2 m ON (t.name = m.name AND t.pos = m.pos AND t.ref = m.ref AND t.alt = m.alt) EXPLAIN SELECT t.id FROM table1 t JOIN table2 m ON (t.name = m.name AND t.pos = m.pos AND t.ref = m.ref AND t.alt = m.alt)

Index for any tables:任何表的索引:

SELECT 
  CONCAT(
    'ALTER TABLE ', 
    TABLE_NAME, 
    ' ', 
    'ADD ', 
    IF(
      NON_UNIQUE = 1, 
      CASE UPPER(INDEX_TYPE) WHEN 'FULLTEXT' THEN 'FULLTEXT INDEX' WHEN 'SPATIAL' THEN 'SPATIAL INDEX' ELSE CONCAT(
        'INDEX ', INDEX_NAME, ' USING ', INDEX_TYPE
      ) END, 
      IF(
        UPPER(INDEX_NAME) = 'PRIMARY', 
        CONCAT(
          'PRIMARY KEY USING ', INDEX_TYPE
        ), 
        CONCAT(
          'UNIQUE INDEX ', INDEX_NAME, ' USING ', 
          INDEX_TYPE
        )
      )
    ), 
    '(', 
    GROUP_CONCAT(
      DISTINCT CONCAT('', COLUMN_NAME, '') 
      ORDER BY 
        SEQ_IN_INDEX ASC SEPARATOR ', '
    ), 
    ');'
  ) AS 'Show_Add_Indexes' 
FROM 
  information_schema.STATISTICS 
WHERE 
  TABLE_SCHEMA = 'your_database' 
  and TABLE_NAME = 'your_table';
-- GROUP BY 
--   TABLE_NAME, 
--   INDEX_NAME 
-- ORDER BY 
--   TABLE_NAME ASC, 
--   INDEX_NAME ASC;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM