【问题标题】:Slow query on update using select count(*)使用 select count(*) 对更新进行慢查询
【发布时间】:2011-11-11 22:34:41
【问题描述】:

我必须计算 table2 中的数字在 table2.a 和 table2.b 范围内的数字之间出现了多少次

即我们想知道我们有多少次:a

我运行了以下查询:

UPDATE table2
 SET occurrence =  
       (SELECT COUNT(*) FROM table1 WHERE start BETWEEN table2.a AND table2.b);



table2 
ID   a   b    occurrence
1    1   10
2    1   20
3    1   25
4    2   30


table1 
ID start col1 col2 col3
1   1
2   7
3  10
4  21
5  25
6  27
7  30

table2 为

  • a、b 和出现的 3 个索引
  • 1567 行(因此我们将在 table2 上 SELECT COUNT(*) 1567 次......)
  • ID 列作为 PK

table1 为

  • 开始时有 1 个索引
  • 42,000,000 行
  • 列开始是“按列开始排序”
  • ID 列作为 PK

==> 2/3 花了 2.5 小时。我需要加快速度...有什么建议吗? :)

【问题讨论】:

  • 你在查询上试过EXPLAIN EXTENDED吗?
  • 是的,但它并没有告诉我太多..

标签: mysql performance select count indexing


【解决方案1】:

我认为 count(*) 使数据库读取数据行,而在您的情况下,它只需要读取索引。试试:

UPDATE table2
 SET occurrence =  
       (SELECT COUNT(1) FROM table1 WHERE start BETWEEN table2.a AND table2.b);

【讨论】:

  • 谢谢,我试过了,整晚都更新了一张桌子。我不确定这是不是最好的方法~
  • 与 count(*) 相同的性能和解释计划?在那种情况下,我猜优化器足够聪明,可以在两种情况下都读取索引。
【解决方案2】:

我会这样做

// use one expensive join
create table tmp
select table2.id, count(*) as occurrence 
from table1
inner join table1
on table1.start between table2.a and table2.b
group by table1.id;

update table2, tmp
set table2.occurrence=tmp.occurrence 
where table2.id=tmp.id;

【讨论】:

  • 这个我没有测量,你可以贴一下SELECT语句的解释计划。然后我们可以进一步讨论
  • 不应该是table1.start而不是table1.id吗?这种方法很有前景!
  • 你切换了table1和table2?
【解决方案3】:

您可以尝试将 id 列添加到表 1 的索引中:

CREATE INDEX start_index ON table1 (start,id);

并将查询重写为

UPDATE table2
 SET occurrence =  
       (SELECT COUNT(id) FROM table1 WHERE start BETWEEN table2.a AND table2.b);

这叫做“覆盖索引”:http://www.simple-talk.com/sql/learn-sql-server/using-covering-indexes-to-improve-query-performance/

-> 表 1 上的整个查询可以通过索引中的数据进行服务 -> 无需对实际记录进行额外的页面查找。

【讨论】:

    【解决方案4】:

    使用存储过程。将 COUNT 的结果保存在局部变量中,然后使用它来运行 UPDATE 查询。

    【讨论】:

      猜你喜欢
      • 2014-09-21
      • 1970-01-01
      • 1970-01-01
      • 2016-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多