【问题标题】:Long running MYSQL query, Frame Table and View with grouping长时间运行的 MYSQL 查询、Frame Table 和 View with grouping
【发布时间】:2013-08-21 22:03:05
【问题描述】:

我有一个 t_date_interval_30 表,它是 365 个日历年日期的笛卡尔积,以及一个以 30 分钟间隔递增的时间字段。我用它作为一个框架来挂电话数据。

t_date_interval_30
DATE, DAYNAME, INTERVAL
'2013-01-01', 'Tuesday', '00:00:00'
'2013-01-01', 'Tuesday', '00:30:00'
'2013-01-01', 'Tuesday', '01:00:00'
'2013-01-01', 'Tuesday', '01:30:00'
'2013-01-01', 'Tuesday', '02:00:00'
'2013-01-01', 'Tuesday', '02:30:00'
ETC...

接下来我有一个视图 v_call_details,它是通话数据的汇总视图。每个呼叫会话发起的呼叫数据汇总为一行 - 每个呼叫会话的源可以有多行;即,呼叫将响铃无应答从一个目标滚动到另一个目标,呼叫的每一段都会增加一个新的记录行。

v_call_details
CLIENT, CSQ, SESS_ID, DATE, CALL_START, CONT_DISP, MET_SLA
'Acme','ACME_CSQ','123-123456789-01','2013-01-01','2013-01-01 00:12:34','ABANDONED',TRUE
'Acme','ACME_CSQ','123-123456998-01','2013-01-01','2013-01-01 00:45:02','HANDLED',TRUE
'Acme','ACME_CSQ','123-123457291-01','2013-01-02','2013-01-02 13:31:58','HANDLED',FALSE
ETC...

所以,当我运行下面的查询时,它需要很长时间。

SELECT
cd.`client`,
cd.`csq`,
di.`date`,
di.`dayname`,
di.`interval`,
count(cd.`sess_id`) AS `calls`,
(count(cd.`sess_id`) - sum(IF(cd.`cont_disp` = 'ABANDONED'
        AND cd.`met_sla` > 0,
    1,
    0))) AS `presented`
FROM
t_date_interval_30 di
    LEFT JOIN
v_call_details cd ON (di.`date` = cd.`date`
    AND di.`interval` = SEC_TO_TIME((TIME_TO_SEC(cd.`call_start`) DIV 1800) * 1800))
WHERE
di.`date` BETWEEN '2013-05-01' AND '2013-05-02'
GROUP BY cd.`csq`, di.`date`, di.`interval`

我从未真正使用过索引(尽管我尝试在 DATE 值和 CALL_START 值中添加一些)。当我运行 EXPLAIN EXTENDED 时,我得到以下结果。

id, select_type,    table,                      type,   possible_keys,  key,    key_len,    ref,    rows,   filtered,   Extra
1,  PRIMARY,        di,                         range,  i_date,         i_date, 3,          ,       96,     100.00,     Using where; Using temporary; Using filesort
1,  PRIMARY,        <derived2>,                 ALL,    ,               ,       ,           ,       153419, 100.00,     ,
2,  DERIVED,        t_cisco_csq_agent_details,  ALL     ,               ,       ,           ,       161925, 100.00,     Using temporary; Using filesort
2,  DERIVED,        t_lkp_clients,              ALL     ,               ,       ,           ,       56,     100.00,     ,

任何建议将不胜感激。现在,如果我运行查询,返回 2 天数据的结果大约需要 70 秒。按照这样的速度,写一份 90 天的报告需要一个半小时……我需要找到一种方法来降低它。

【问题讨论】:

    标签: mysql indexing view left-join


    【解决方案1】:

    首先,不要假设 90 天的数据需要 45 倍于 2 天的工作量。您的查询正在对呼叫详细信息表进行全面扫描,这可能会造成很大的工作量。 MySQL 可以通过等值连接将日期条件从di 传播到cd。我不确定它是否在这种情况下(因为第二个条件)。

    其次,您正在使用视图。这可能会导致无法真正提高性能。您可以尝试,但您应该尝试在没有视图的情况下编写查询。

    我的下一个问题是运行需要多长时间:

    select cd.csq, cd.`date`,
           SEC_TO_TIME((TIME_TO_SEC(cd.`call_start`) DIV 1800) * 1800)) as interval,
           count(*)
    from v_call_details cd 
    WHERE cd.`date` BETWEEN '2013-05-01' AND '2013-05-02';
    

    如果这需要合理的时间,则测试 90 天。如果可行,那么您可以先进行聚合,然后再加入di 表。这只是一个想法。我怀疑真正的性能问题在视图中。

    【讨论】:

      猜你喜欢
      • 2014-01-28
      • 2019-07-09
      • 1970-01-01
      • 1970-01-01
      • 2012-03-11
      • 1970-01-01
      • 2018-04-20
      • 2011-04-22
      • 2018-10-09
      相关资源
      最近更新 更多