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

时间:2016-02-24 19:22:45

标签: mysql sql database join

我有两张桌子:

第一个table1是动态创建的(当用户从​​Web服务器提交数据时),通常是~50K行。第二个表是查找表table2并且具有~10Mil行。

我试图按如下方式将两个表连接在一起:

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);

我在{{1}中已将列name(VARCHAR),pos(INT),ref(CHAR)和alt(CHAR)编入索引但是查询仍然需要很长时间才能完成。

关于这里可能出现什么问题的任何指示?

由于

table2的输出:

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

3 个答案:

答案 0 :(得分:7)

name, pos, ref, alt

上创建复合索引

喜欢

INDEX theIndex (name,pos,ref, alt)

另外,4个单指数会有所帮助 - 见http://dev.mysql.com/doc/refman/5.7/en/index-merge-optimization.html - 但不如复合指数那么多。

答案 1 :(得分:2)

在这里尝试两件事:

  1. 第一个是最简单的 - 更改join子句的顺序以将varchar列移动到最后。
  2.   

    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. 这是一项更多工作,但添加一个新的计算列,根据4列生成数字哈希。删除pos,ref,alt和name上的索引,并向哈希列添加新索引。然后在join子句中包含hash列。
    2.   

      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);

      编辑:在不查看数据库和查询执行计划的情况下,很难解决这个问题,但我的猜测是MySQL很难加入VARCHAR列。你能用

      的结果更新你的问题吗?
        

      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)

答案 2 :(得分:0)

任何表的索引:

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;