加快 SQL 大型 table 查询的方法

Ways to speed up SQL query on large table

我有一个 MySQL table 1000 万行和 3 列,格式如下:

id                                     time                               num

ca65e871-d758-437e-b76f-175234760e7b  2020-11-14T23:08:05.553770Z         11112222222
...

我正在尝试计算特定数量和所需时间范围内的出现次数,如下所示:

"SELECT COUNT(*) FROM TABLE_NAME WHERE time >'2020-11-14T23:08:05.553752Z' and num = '11112222222'"

我是来自 Python 环境 (python 3.x) 的 运行 查询,它使用 pymysql 包连接到 MySQL 数据库。在 10MM 行上,此执行持续约 2.8 秒。在 timenum 列上添加索引后,执行速度几乎快了一倍:1.5 秒.

我的问题是我可以进一步加快速度吗?

理想情况下,执行时间应该在 200 毫秒以下,所以我不知道这是否可能。提前致谢!

对于此查询:

SELECT COUNT(*) 
FROM TABLE_NAME 
WHERE time > '2020-11-14T23:08:05.553752Z' AND num = '11112222222'

您想要 (num, time) 上的多列索引。索引中列的顺序很重要。您希望首先具有相等谓词的列,然后是具有不等谓词的列。

我对数据类型有点怀疑。如果 num 是数字数据类型(看起来像 int),那么您应该根据文字数字过滤它:

num = 11112222222

进一步加快查询速度的唯一方法是缩小数据类型。

num = '11112222222' 不需要更改,但是...

BIGINT 是 8 个字节。如果你能忍受 40 亿的限制,请使用 INT UNSIGNED(4 个字节)。

不幸的是,MySQL 无法将字符串 '2020-11-14T23:08:05.553770Z' 理解为 DATETIME(也不是 TIMESTAMP) 如果 time 是 VARCHAR(27),然后一切正常。但是如果你可以切换到兼容的格式,很多 space 将被保存为 DATETIME(6),它只有 8 个字节(而 varchar 为 28 个字节)。

UUIDs 由于其随机性,体积庞大且效率低下。您可能正在使用 CHAR(36) CHARACTER SET ascii —— 36 字节。将其打包(参见 MySQL 8.0)为 `BINARY(16) -- 16 字节。

这些会显着缩小 table 和索引,从而提高性能。

对于 UUID 的转换代码:http://mysql.rjweb.org/doc.php/uuid#code_to_do_it 另外 MySQL 8.0 也有一对类似的内置函数。

此外,TZ 不是 DATETIME(6) 的有效字符,因此需要进行一些编辑。