MySQL查询需要很长时间才能执行

时间:2014-07-05 22:11:36

标签: mysql sql database query-optimization inner-join

我编写了一个连接三个不同表的查询。表格的粗略描述如下:

Table 1: account_data
columns: id(pk), property_id(fk), account_id(fk), value, status
No Of Data: around 30 milions

Table 2: account
columns: id(pk), service_id(fk), status
No Of Data: around 5 milions

Table 3: property
columns: id(pk), create_analytics(index), status, uri
No Of Data: few hundreds

查询如下:

SELECT ad.value, p.uri, count(ad.id)
FROM account_data ad 
     INNER JOIN property p ON ad.property_id = p.id AND (p.status = 1) 
     INNER JOIN account ac ON ad.account_id = ac.id AND (ac.status = 1) 
     WHERE (p.create_analytics = '1' AND ac.service_id = ?) AND (ad.status = 1) 
GROUP BY ad.property_id, ad.value

一开始查询花了太长时间。在'create_analytics'列上创建索引后,它明显下降。

但是,查询花了太长时间(超过3分钟)。我尝试通过按列(property_id和value)创建索引,在'status'列上创建索引,但两者都没有显示为改进。

只是想知道,有没有其他方法可以重写此查询以使其更快?或者我错过了创建索引的任何内容,更改顺序会有帮助吗?

期待您解决此问题的所有想法/建议。提前谢谢。

3 个答案:

答案 0 :(得分:1)

此外,如果您当前的create_analytics目前是VARCHAR,请尝试将其更改为CHAR,或者更好的是,如果该字段中的字符串种类有限,请将其更改为ENUM。

变量变量很灵活,可以节省未使用字符的空间,但MySQL必须工作 查看是否有其他字段可以修复,以便MySql可以预先判断行的宽度。

确保所有联接的类型相同,我猜你的ID是INT,确保你没有在某处混合BIGINT。

最后,尝试将creating_analytics移动到JOIN部分,因此您可以为WHERE子句提供较小的结果集。

答案 1 :(得分:1)

删除您当前拥有的索引(PK除外),然后尝试在以下内容中添加(复合)索引:

account_data (property_id,status)

property (status,create_analytics)

account (status,service_id)

答案 2 :(得分:0)

很大程度上取决于您期望数据更改的频率以及您正在使用的其他约束,但您可以尝试使用实体化视图以及视图本身的索引。注意,您可以在MySQL中的物化视图上配置刷新策略。

来自http://www.fromdual.com/mysql-materialized-views;

刷新实体化视图

物化视图可以以不同种类刷新。它们可以刷新:

  1. 从不(仅在开始时使用一次,仅适用于静态数据)
  2. 按需(例如每天一次,例如在夜间加载后)
  3. 立即(在每个陈述之后)
  4. 可以通过以下方式完成刷新:

    1. 完全(缓慢,从头开始)
    2. 延迟(快速,通过日志表)
    3. 将更改信息存储在日志表中。还可以生成一些快照或延时状态:

      1. 刷新最新
      2. 刷新完整