Bla*_*bam 3 mysql performance index query select
有一个包含 25.000.000 个条目的表,我有以下查询,该查询每 2 秒启动一次,这会导致非常高的负载(在 Amazon AWS 中高达 40 AAS)。执行时间需要20秒到5分钟,甚至会导致用户浏览器超时,掉线率很高。
SELECT COUNT ( * ) AS `chk`
FROM ( SELECT `item_id`
FROM `items`
WHERE `item_status` IN (...)
AND `item_type` = ?
AND `user_id` != ?
AND `item_name` IN (...)
LIMIT 3
) AS OTHERS
;
Run Code Online (Sandbox Code Playgroud)
索引优化已完成 - 、、 和user_id
均已item_name
建立索引(每列一个索引)。item_type
item_status
更多信息:
varchar
128请注意,在大约 50% 的情况下,MySQL 必须检查完整的表,因为找到的项目少于 3 个。因此,该限制仅在商品数量超过 3 件的情况下才有用。
虽然我对某些结果进行 Redis 缓存,但对于此查询来说这是不可能的,因为始终需要精确的结果。随着数据库以每秒约 1 个条目的速度增长,查询性能很快就会变差。
虽然过去我可以通过索引解决大多数问题,但现在我遇到了一个严重的问题。想过用一些触发器或视图来解决问题,但我不确定这是否有帮助?在高度活跃的生产数据库中,在不知道是否能解决问题的情况下进行此类更改是危险的。
我向专业人士提出的问题是:如何使用 MySQL 解决该问题?
小智 9
您可以尝试使用复合索引。
\n您的索引可能如下所示:
\nINDEX (item_type, item_name, item_status, user_id)\n
Run Code Online (Sandbox Code Playgroud)\n该索引应该允许 MySQL 有效地查找所有行,而不必从实际表中查找任何行。
\n列的顺序在这里很重要:
\nitem_type
首先,因为您在列上有一个相等过滤器。item_name
并排item_status
在第二和第三位,因为两者都使用IN
. 列的顺序可以更改,但因为item_name
基数可能比item_status
首先使用它可能要快一些。user_id
排在最后是因为它使用了不等式过滤器,而该过滤器无法通过索引有效处理。一般来说,MySQL 每个表\xc2\xb9 只会使用 1 个索引,因此拥有超过 1 个索引并没有什么帮助。
\n另外,如果索引看起来不能过滤足够的行(有足够的行),MySQL 也不会使用索引。查询计划器根据表和索引统计信息计算出这样做的原因是,当使用索引时,MySQL仍然需要查找表中的原始行(除非你有一个覆盖索引\xc2\xb2),这有点昂贵,所以使用索引来查找很多行可以实际上比全表扫描慢。
\n考虑到表中的行数,大多数(如果不是全部)4 个现有索引可能每个值的行数过多,并且 MySQL 甚至不会考虑此查询。尽管这实际上取决于数据分布和基数。
\n您可以检查使用了哪些索引以及它们是否覆盖或不使用EXPLAIN
. 例如
EXPLAIN SELECT COUNT ( * ) AS `chk` FROM ( SELECT `item_id` FROM `items` WHERE `item_status` IN (...) AND `item_type` = ? AND `user_id` != ? AND `item_name` IN (...) LIMIT 3 ) AS OTHERS;\n
Run Code Online (Sandbox Code Playgroud)\n如果您使用 MySQL 8,您还可以使用它EXPLAIN ANALYZE
来实际了解 MySQL 如何通过计时读取和过滤数据。
Rick James 写了一篇很棒的文档,介绍如何为 SELECT 构建最佳索引,我推荐您阅读。他还写了一篇关于复合(复合)索引的文档,我也可以推荐。
\n将来,请尝试至少提供表架构和索引(您可以用于SHOW CREATE TABLE ?
此)以及运行有问题的查询的输出EXPLAIN
以及 MySQL 版本。这减少了我们必须进行的猜测,并使我们能够给出更具体、更好的答案。
\xc2\xb9 MySQL 可以使用超过 1 个索引的优化称为索引合并优化,但它只在极少数情况下有效,应该避免。
\n\xc2\xb2 覆盖索引是包含查询中使用的所有列的索引。由于所有列都已经在索引中,MySQL 不需要从表本身获取其他列。我在这个答案中提出的索引是覆盖索引的一个示例。
\n