【问题标题】:Slow MySQL query for relatively small table with proper primary key and index使用适当的主键和索引对相对较小的表进行慢速 MySQL 查询
【发布时间】:2015-11-12 20:16:06
【问题描述】:

我在 3 个表上有一个 select 语句; T1 和 T2 可以连接,T2 和 T3 可以连接。 T3 是一个只有 42 行的表。 T2 真的很大,大约有 40 亿行,T1 是 750,000 条记录。我想要的是对于 T1 中的所有记录,我想从 T3 中获取相关数据

如果我对所有 3 个表进行如下连接,则查询需要很长时间才能运行:

select T1.A, T2.B, T3.C, T3.D from 
T1, T2, T3 where T1.A = T2.A 
and T1.B = T2.B and T2.C = T3.C

但如果我从查询中取出 T3,查询会运行得更快。我还使用EXPLAIN 来查找查询路径。看起来对于 T3,它正在执行全表扫描。即,键列是 NULL 。

所以,我的问题是它为什么要这样做?

T3 有一个主键,它是一个相对较小的表。我的整体查询是否很慢,因为在 T1 和 T2 连接之后,对于所有剩余的记录,它正在使用 T3 进行全表扫描?因此,如果在 T1 和 T2 连接后有 700,000 条记录,那么对于这 700,000 条记录中的每一条,它都在全面扫描 T3 表。那么,这就像进行 700,000 x 42 扫描?


更新

为了便于理解,我用 T1、T2、T3 替换了我原来的表名。但这是我的实际查询:

select vc.vkey, vc.enst, vi.`effect_code`, te.effect, te.impact
from Variants vc, var_RVS.variant_impact vi, var_RVS.`types_effects` te
where vi.effect_code = te.eid
and vc.vkey = vi.vkey 

这里是解释语句的输出:

+----+-------------+-------+------+-------------------------------------+-------------+---------+---------------------------------+------+-------------+
| id | select_type | table | type | possible_keys                       | key         | key_len | ref                             | rows | Extra       |
+----+-------------+-------+------+-------------------------------------+-------------+---------+---------------------------------+------+-------------+
|  1 | SIMPLE      | te    | ALL  | PRIMARY                             | NULL        | NULL    | NULL                            |   42 | NULL        |
|  1 | SIMPLE      | vi    | ref  | canonical_enst,vkey_idx,effect_code | effect_code | 4       | var_RVS.te.eid                  |  981 | Using where |
|  1 | SIMPLE      | vc    | ref  | allVsAllXref,vkey_enst              | vkey_enst   | 788     | var_RVS.vi.vkey,var_RVS.vi.enst |    1 | Using where |
+----+-------------+-------+------+-------------------------------------+-------------+---------+---------------------------------+------+-------------+

【问题讨论】:

  • 你能发布你的解释结果吗?
  • 架构也会有所帮助。 [A,B] 是复合主键吗?
  • 尝试在该语法中使用 JOIN 而不是 SQL。
  • 你有什么证据表明te (``T3?) has any indices, or that eid` (C?) 是主键?
  • 我查看了 T3 的表结构并在 T3 上运行了“显示索引”。

标签: mysql performance join


【解决方案1】:

除非 T3.C 上有索引,否则它必须扫描所有 T3 以找到满足T2.C = T3.C 的记录。这与密钥无关;鉴于您当前的架构(据我了解),没有其他方法可以找到满足此要求的记录。

【讨论】:

  • T3.C 是主键,也是索引。
  • @ayesandarmoe:你认为这无关紧要吗?
【解决方案2】:

在最坏的情况下,输出将是 750K * 4B * 42 = 126 万亿行。

EXPLAIN 估计 42 * 981 * 1 = 4 万行。

如果存在vi.effect_code = te.eid 没有匹配行的情况,则可能是较小的数字。

你没有过滤掉行。你期待什么?

EXPLAIN 表明每个阶段都存在良好的索引,因此查询尽可能快。

“慢”有多慢? 你得到了多少行?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-31
    • 1970-01-01
    • 1970-01-01
    • 2018-11-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多