【问题标题】:MySql querying taking too longMySql 查询耗时过长
【发布时间】:2017-04-30 16:27:13
【问题描述】:

我有一张桌子

CREATE TABLE temp (
    i1 DECIMAL(10, 5),
    i2 DECIMAL(10, 5),
    i3 DECIMAL(10, 5),
    i4 DECIMAL(10, 5),
    i5 DECIMAL(10, 5),
    i6 DECIMAL(10, 5),
    i7 DECIMAL(10, 5),
    i8 DECIMAL(10, 5),
    i9 DECIMAL(10, 5),
    o1 DECIMAL(10, 5),
    o2 DECIMAL(10, 5),
    o3 DECIMAL(10, 5),
    o4 DECIMAL(10, 5),
    o5 DECIMAL(10, 5),
    o6 DECIMAL(10, 5),
    o7 DECIMAL(10, 5),
    o8 DECIMAL(10, 5),
    o9 DECIMAL(10, 5)
); 
CREATE INDEX input_data_index
ON temp (i1, i2, i3, i4, i5, i6, i7, i8, i9);
CREATE INDEX test_index
ON temp (o1); 

我正在尝试使用此查询搜索此表:

SELECT * FROM temp t
INNER JOIN temp x
ON t.i1 = x.i1 
AND t.i2 = x.i2
AND t.i3 = x.i3
AND t.i4 = x.i4
AND t.i5 = x.i5
AND t.i6 = x.i6
AND t.i7 = x.i7
AND t.i8 = x.i8
AND t.i9 = x.i9
WHERE t.o1 != x.o1; 

该表包含 180,362 行。如果我取出 where 子句,它只需要 0.157 秒即可运行,但是使用 where 子句需要很长时间才能运行(超过 300 秒),此时我只需取消它。

为什么添加 where 子句需要这么长时间才能运行? 您对如何加快速度有什么建议吗?

编辑:

当我使用原来的索引运行解释语句时,我得到:img

当我使用@Simulant 建议的语句运行解释语句(将 o1 添加到索引中)时,我得到:img2

但是这个查询仍然需要很长时间才能执行。

【问题讨论】:

  • 它可能在连接上单独为每一行运行 where 查询,即它正在执行数千个查询。
  • 这种问题是糟糕设计的表现
  • 尝试删除o1 上的索引。这可能会使优化器感到困惑。
  • @Strawberry 有关如何修复设计的任何建议?
  • 任何时候你枚举了列(比如说2个以上),你可以确定你的设计是有缺陷的。我不知道 i 和 o 是什么,所以我无法进一步评论,但请参阅规范化。

标签: mysql database performance database-performance database-optimization


【解决方案1】:

如果您想要 o1 的值,其中 i 值相同,您可以考虑:

select i1, i2, i3, i4, i5, i6, i7, i8, i9,
       group_concat(o1)
from temp
group by i1, i2, i3, i4, i5, i6, i7, i8, i9;

这不是完全相同的结果集,但它可能满足您的需求。

【讨论】:

  • 谢谢,但不,它不会产生预期的结果。另外我不知道谁对你的帖子投了反对票,哈哈
  • 如果您将鼠标悬停在向下箭头上,它可能会提供线索。
  • @User9813 。 . .如果唯一的原因是它产生单例,那么你可以包含having min(o1) <> max(o1)
  • @User9813 - 它以什么方式不会产生预期的结果?您是说它没有 40 列,而 i 列重复了吗?或者您需要所有 20 个 o 列?还是别的什么?
  • @RickJames 我的意思是我想要原始表(没有重复的列),我现在意识到你看不到,因为我在原始选择语句中使用了“*”。此外,我只想查看包含 where i1, i2 ... i9 对于两个表相同但 o1 对于两个表不同的行。
【解决方案2】:

i1, i2, i3, i4, i5, i6, i7, i8, i9 列在同一个索引中编入索引,因此没有where 的查询将被索引充分利用。您的列o1 在另一个索引中被索引。但是一个查询一次只能对一张表使用一个索引。您应该做的是将查询所需的所有列添加到同一个索引中。

CREATE INDEX input_data_index
ON temp (i1, i2, i3, i4, i5, i6, i7, i8, i9, o1);

使用explain 语句可以帮助您了解索引减少扫描行的效果。

【讨论】:

  • 基于此推理,将WHERE 更改为HAVING 会有所帮助。
【解决方案3】:

INDEX((i1, i2, i3, i4, i5, i6, i7, i8, i9,  o1)

并将 WHERE 子句更改为

WHERE t.o1 > x.o1; 

这会将输出的行数减少一半,并且可能会改变查询的执行方式。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-12
    • 2019-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-03
    • 2015-10-23
    相关资源
    最近更新 更多