如何使用 MySQL 中的 Between 子句加快计数(不同)
How to speed up count(distinct) with Between clause in MySQL
我有一个 MySQL table 的 1000 万行和 3 列,格式如下:
id time num
ca65e871-d758-437e-b76f-175234760e7b 2020-11-14 23:08:05.553770 11112222222
...
对于下面的第一个查询 运行,我在 (num, time)
上为 table 建立了索引,它运行得非常快(<5 毫秒处理 1000 万行 table):
SELECT COUNT(*)
FROM TABLE_NAME
WHERE time >= '2020-11-14 23:08:05.553752' AND num = 11112222222
但是我还需要在同一个 table 上执行 count(distinct)
和 between
子句,像这样:
SELECT COUNT(DISTINCT num)
FROM TABLE_NAME
WHERE time >= '2020-11-14 23:08:05.553752'
AND num BETWEEN (11112222222 - 30)
AND (11112222222 + 30)
事实证明这要慢得多,大约 200 毫秒。
有没有办法加快第二个查询在同一个 table?
上的执行时间
如果你的 MySQl 是 8+,那么试试:
WITH RECURSIVE
cte AS ( SELECT 11112222222 - 30 num
UNION ALL
SELECT num + 1 FROM cte WHERE num < 11112222222 + 30 )
SELECT COUNT(*)
FROM cte
WHERE EXISTS ( SELECT NULL
FROM TABLE_NAME
WHERE TABLE_NAME.num = cte.num
AND time >= '2020-11-14 23:08:05.553752' )
如果您经常执行此类查询,那么我建议使用从 -30 到 30 的数字创建服务 table,并使用它代替递归 CTE。
这是一个二维问题。而您的 WHERE
子句就像一个“边界框”。
添加 INDEX(time, num)
给优化器另一个选择。
如果您希望有基于 2 个范围的更复杂的查询,请参阅 http://mysql.rjweb.org/doc.php/find_nearest_in_mysql
我有一个 MySQL table 的 1000 万行和 3 列,格式如下:
id time num
ca65e871-d758-437e-b76f-175234760e7b 2020-11-14 23:08:05.553770 11112222222
...
对于下面的第一个查询 运行,我在 (num, time)
上为 table 建立了索引,它运行得非常快(<5 毫秒处理 1000 万行 table):
SELECT COUNT(*)
FROM TABLE_NAME
WHERE time >= '2020-11-14 23:08:05.553752' AND num = 11112222222
但是我还需要在同一个 table 上执行 count(distinct)
和 between
子句,像这样:
SELECT COUNT(DISTINCT num)
FROM TABLE_NAME
WHERE time >= '2020-11-14 23:08:05.553752'
AND num BETWEEN (11112222222 - 30)
AND (11112222222 + 30)
事实证明这要慢得多,大约 200 毫秒。 有没有办法加快第二个查询在同一个 table?
上的执行时间如果你的 MySQl 是 8+,那么试试:
WITH RECURSIVE
cte AS ( SELECT 11112222222 - 30 num
UNION ALL
SELECT num + 1 FROM cte WHERE num < 11112222222 + 30 )
SELECT COUNT(*)
FROM cte
WHERE EXISTS ( SELECT NULL
FROM TABLE_NAME
WHERE TABLE_NAME.num = cte.num
AND time >= '2020-11-14 23:08:05.553752' )
如果您经常执行此类查询,那么我建议使用从 -30 到 30 的数字创建服务 table,并使用它代替递归 CTE。
这是一个二维问题。而您的 WHERE
子句就像一个“边界框”。
添加 INDEX(time, num)
给优化器另一个选择。
如果您希望有基于 2 个范围的更复杂的查询,请参阅 http://mysql.rjweb.org/doc.php/find_nearest_in_mysql