Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何优化此mysql查询以找到最大的同时调用数?_Mysql - Fatal编程技术网

如何优化此mysql查询以找到最大的同时调用数?

如何优化此mysql查询以找到最大的同时调用数?,mysql,Mysql,我正在计算最大同时呼叫数。我的查询(我相信是准确的)太长了,因为有250000行。cdrs表如下所示: +---------------+-----------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +---------------+-----------------

我正在计算最大同时呼叫数。我的查询(我相信是准确的)太长了,因为有250000行。cdrs表如下所示:

+---------------+-----------------------+------+-----+---------+----------------+
| Field         | Type                  | Null | Key | Default | Extra          |
+---------------+-----------------------+------+-----+---------+----------------+
| id            | bigint(20) unsigned   | NO   | PRI | NULL    | auto_increment |
| CallType      | varchar(32)           | NO   |     | NULL    |                |
| StartTime     | datetime              | NO   | MUL | NULL    |                |
| StopTime      | datetime              | NO   |     | NULL    |                |
| CallDuration  | float(10,5)           | NO   |     | NULL    |                |
| BillDuration  | mediumint(8) unsigned | NO   |     | NULL    |                |
| CallMinimum   | tinyint(3) unsigned   | NO   |     | NULL    |                |
| CallIncrement | tinyint(3) unsigned   | NO   |     | NULL    |                |
| BasePrice     | float(12,9)           | NO   |     | NULL    |                |
| CallPrice     | float(12,9)           | NO   |     | NULL    |                |
| TransactionId | varchar(20)           | NO   |     | NULL    |                |
| CustomerIP    | varchar(15)           | NO   |     | NULL    |                |
| ANI           | varchar(20)           | NO   |     | NULL    |                |
| ANIState      | varchar(10)           | NO   |     | NULL    |                |
| DNIS          | varchar(20)           | NO   |     | NULL    |                |
| LRN           | varchar(20)           | NO   |     | NULL    |                |
| DNISState     | varchar(10)           | NO   |     | NULL    |                |
| DNISLATA      | varchar(10)           | NO   |     | NULL    |                |
| DNISOCN       | varchar(10)           | NO   |     | NULL    |                |
| OrigTier      | varchar(10)           | NO   |     | NULL    |                |
| TermRateDeck  | varchar(20)           | NO   |     | NULL    |                |
+---------------+-----------------------+------+-----+---------+----------------+
我有以下索引:

+-------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name        | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| cdrs  |          0 | PRIMARY         |            1 | id          | A         |      269622 |     NULL | NULL   |      | BTREE      |         |               |
| cdrs  |          1 | id              |            1 | id          | A         |      269622 |     NULL | NULL   |      | BTREE      |         |               |
| cdrs  |          1 | call_time_index |            1 | StartTime   | A         |      269622 |     NULL | NULL   |      | BTREE      |         |               |
| cdrs  |          1 | call_time_index |            2 | StopTime    | A         |      269622 |     NULL | NULL   |      | BTREE      |         |               |
+-------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
我正在运行的查询是:

SELECT MAX(cnt) AS max_channels FROM
  (SELECT cl1.StartTime, COUNT(*) AS cnt
    FROM cdrs cl1
    INNER JOIN cdrs cl2
    ON cl1.StartTime
    BETWEEN cl2.StartTime  AND cl2.StopTime
    GROUP BY cl1.id)
  AS counts;


似乎我每天都必须将这些数据分块,并将结果存储在一个单独的表中,如
同步调用

内联视图并非绝对必要。(使用内联视图在查询上运行解释的时间是正确的,解释将具体化内联视图(即运行内联视图查询并填充派生表),然后对外部查询进行解释

请注意,此查询将返回等效的结果:

SELECT COUNT(*) AS max_channels
  FROM cdrs cl1
  JOIN cdrs cl2
    ON cl1.StartTime BETWEEN cl2.StartTime  AND cl2.StopTime
 GROUP BY cl1.id
 ORDER BY max_channels DESC
 LIMIT 1
尽管它仍然需要完成所有的工作,而且可能没有更好的表现;解释应该运行得更快(我们希望在额外的专栏中看到“使用临时文件;使用文件排序”)


结果集中的行数将是表中的行数(~250000行),这些行需要排序,所以这将是一段时间。更大的问题(我的直觉告诉我)是连接操作

我想知道如果在谓词中交换cl1和cl2,解释(或性能)是否会有所不同,即

ON cl2.StartTime BETWEEN cl1.StartTime AND cl1.StopTime
我在想,只是因为我想尝试一个相关的子查询。这大约是250000次执行,而且不可能再快了

SELECT ( SELECT COUNT(*) 
           FROM cdrs cl2
          WHERE cl2.StartTime BETWEEN cl1.StartTime AND cl1.StopTime
       ) AS max_channels
     , cl1.StartTime
  FROM cdrs cl1
 ORDER BY max_channels DESC
 LIMIT 11
您可以对此进行解释,我们仍然会看到“使用临时;使用文件排序”,它还将显示“依赖子查询”


显然,在cl1表上添加一个谓词可以减少要返回的行数(例如,只检查过去15天);这应该会加快速度,但这并不能得到您想要的答案

WHERE cl1.StartTime > NOW() - INTERVAL 15 DAY

(我在这里的任何思考都不是对您的问题的肯定回答,也不是对性能问题的解决方案;它们只是思考。)

我确信您不仅想知道最大同时呼叫数,而且想知道何时发生

我将创建一个包含每分钟时间戳的表

CREATE TABLE times (ts DATETIME UNSIGNED AUTO_INCREMENT PRIMARY KEY);
INSERT INTO times (ts) VALUES ('2014-05-14 00:00:00');
. . . until 1440 rows, one for each minute .  . .
然后把它和电话联系起来

SELECT ts, COUNT(*) AS count FROM times 
JOIN cdrs ON times.ts BETWEEN cdrs.starttime AND cdrs.stoptime 
GROUP BY ts ORDER BY count DESC LIMIT 1;
以下是我的测试结果(在MacBookPro上运行的Linux虚拟机上的MySQL 5.6.17):

这实现了几个目标:

  • 将检查的行数减少两个数量级
  • 将执行时间从3小时以上减少到1分钟左右
  • 还返回找到最高计数时的实际时间戳
以下是对我的问题的解释:

explain select ts, count(*) from times join cdrs on times.ts between cdrs.starttime and cdrs.stoptime group by ts order by count(*) desc limit 1;
+----+-------------+-------+-------+---------------+---------+---------+------+--------+------------------------------------------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows   | Extra                                          |
+----+-------------+-------+-------+---------------+---------+---------+------+--------+------------------------------------------------+
|  1 | SIMPLE      | times | index | PRIMARY       | PRIMARY | 5       | NULL |   1440 | Using index; Using temporary; Using filesort   |
|  1 | SIMPLE      | cdrs  | ALL   | starttime     | NULL    | NULL    | NULL | 260727 | Range checked for each record (index map: 0x4) |
+----+-------------+-------+-------+---------------+---------+---------+------+--------+------------------------------------------------+

请注意列中的数字,并将其与原始查询的解释进行比较。您可以通过将这些数字相乘来估计检查的行总数(但如果您的查询不是简单的,则会变得更复杂).

需要多长时间?您希望需要多长时间?另外,您可以向我们展示查询的解释吗?我认为这无关紧要,但您不需要在子查询中选择
cl1.StartTime
。您只需要
COUNT(*)
@AndyLester现在三个小时就要开始了哈哈。我本来打算做一个解释,但不想再让它慢下来。不需要解释,它会告诉你这是在进行625亿次比较,很可能还将临时表存储在磁盘上。我想你需要找到另一种方法,甚至不是SQL,来找到这个t韩在一张大桌子上进行了自我连接。@Jason,你可能比我更了解钱。尽管如此,我还是觉得选择浮点而不是十进制是非常奇怪的!非常感谢你的思考;)我在你的第二次查询中出现了以下错误:
where子句中的未知列“cl1.EndTime”
@Jason:完全是我的错。您查询中的列名是
StopTime
,我在回答中的每一处都错误地键入了
EndTime
。我会修改我的答案,使列名与你的列名匹配。哈,我应该抓住这个。下面是@Jason:第二个查询的解释显示,覆盖索引将满足查询,但子查询的执行仍然是269622次。(性能是简单的数学运算:无论做
计数需要多长时间(1)
使用覆盖索引进行查询,执行次数为269622次。我正在做更多的测试,您的第二次查询似乎非常有效。特别是当我包含WHERE子句(如您的示例)时……最后10天需要~6秒。您所说的
计数(1)是什么意思这个代码看起来很有前途。但是,创建一个时间表似乎很奇怪。我是否需要连续地为每分钟插入新的行?而且,在我看来,这会考虑在同一分钟内同时调用,对吗?很明显,一个调用可以在分钟的开始结束,另一个可以在MI结束时开始。nute.@Jason:这也没有考虑通话持续时间少于一分钟的边缘情况,即在同一分钟内开始和停止(不要跨越边界)。但是,这些可能是可以忽略的边缘情况,这可能是一个足够接近的近似值。(我认为这里真正的性能提升是只进行了一天的检查。您还可以在我的回答中添加谓词
cl1.StartTime>='2014-05-14'和cl1.StartTime<'2014-05-14'+间隔1天
,测试查询(使用相关子查询),以获得相同的结果。
explain select ts, count(*) from times join cdrs on times.ts between cdrs.starttime and cdrs.stoptime group by ts order by count(*) desc limit 1;
+----+-------------+-------+-------+---------------+---------+---------+------+--------+------------------------------------------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows   | Extra                                          |
+----+-------------+-------+-------+---------------+---------+---------+------+--------+------------------------------------------------+
|  1 | SIMPLE      | times | index | PRIMARY       | PRIMARY | 5       | NULL |   1440 | Using index; Using temporary; Using filesort   |
|  1 | SIMPLE      | cdrs  | ALL   | starttime     | NULL    | NULL    | NULL | 260727 | Range checked for each record (index map: 0x4) |
+----+-------------+-------+-------+---------------+---------+---------+------+--------+------------------------------------------------+