概述:
我有一个构建查询语句的系统。其中一些必须根据传递到系统中的设置参数将一些表连接到其他表。在对创建的查询运行一些性能测试时,我注意到一些查询正在进行全表扫描,在许多情况下,从我读到的内容来看,这对于大型表来说并不好。
我正在尝试做什么:
1 - Remove the full table scans
2 - Speed up the Query
3 - Find out if there is a more efficient query I can have the system build instead
查询:
SELECT a.p_id_one, b.p_id_two, b.fk_id_one, c.fk_id_two, d.fk_id_two,
d.id_three, d.fk_id_one
FROM ATable a
LEFT JOIN BTable b ON a.p_id_one = b.fk_id_one
LEFT JOIN CTable c ON b.p_id_two = c.fk_id_two
LEFT JOIN DTable d ON b.p_id_two = d.fk_id_two
WHERE a.p_id_one = 1234567890
查询时间
Showing rows 0 - 10 (11 total, Query took 0.0016 seconds.)
当前问题:
1 - 我的系统/DBMS (phpmyadmin) 的查询时间在 0.0013 秒到 0.0017 秒之间。
- 我做了什么来解决?
全表扫描或“ALL”类型查询正在表(“BTable”、“DTable”)上运行,因此我尝试在适当的 ID 上使用 FORCE INDEX。 使用 FORCE INDEX 会删除全表扫描,但不会加快速度 表现。 我仔细检查了我的 fk_constraints 和索引关系,以确保我没有遗漏任何内容。到目前为止,一切顺利。
2 - Advisor 显示多个警告,其中一些与全表扫描和索引相关。
问题:
假设所有索引均可用并已创建
1 - 有更好的方法来执行此查询吗?
2 - 有多少连接算过多连接?
3 - 连接可能是问题所在吗?
4 - 问题是否出在 WHERE 子句中?
5 - 我可能错过了哪些优化技术/工具?
6 - 如何让该查询以 0.0008 到 0.0001 之间的速度执行?
如果需要图像和视觉效果来帮助澄清我的情况,请在下面的评论中提问。我感谢任何和所有的帮助。
谢谢=)
最佳答案
“p_id_one”并没有告诉我们太多信息。这是自动增量吗?真实的列名称有时会提供基数和意图的重要线索。正如威廉所说,“这个问题肯定还有更多问题”和“总体问题是什么”。
LEFT
——你需要它吗?它阻止某些形式的优化;如果“右”表格行不是可选的,请将其删除。
WHERE a.p_id_one = 1234567890
需要 INDEX(p_id_one)
。这已经是主键
了吗?在这种情况下,不需要额外的 INDEX
。 (请提供SHOW CREATE TABLE
。)
这些真的是您正在选择
的列/表达式吗?它可以产生影响——尤其是在建议使用“覆盖索引”作为优化时。
请提供 EXPLAIN SELECT ...
的输出(这不是您提供的讨论。)该输出将有助于提供 1:many、基数等线索。
如果这些是FOREIGN KEY
,则您已经在 b.fk_id_one、c.fk_id_two、d.fk_id_two 上有索引;所以没有什么可做的了。
对于涉及 4 个表的查询来说,1.6 毫秒是一个绝佳的时间。不要计划显着加快速度。您可能每秒处理数百个连接,执行数千个类似的查询。您还需要更多吗?
你使用的是InnoDB吗?这样更适合并发访问。
您的示例似乎没有任何全表扫描;请提供一个例子。
10 行表上的ALL
无需担心。对于一百万行的表来说这是一件大事。您的 table 会显着增长吗?在担心 ALL
时,您应该注意这一点:全表扫描有时比使用“完美”索引更快。当估计的行数超过表的大约 20% 时,优化器决定扫描。表扫描非常高效,因为它直接扫描整个表,即使跳过 80% 的行也是如此。使用索引更复杂——扫描索引,但是对于在索引中找到的每一行,需要在数据中查找以找到该行。如果您认为不应该看到ALL
,那么可能索引的选择性不强。别担心。
不要使用FORCE INDEX
- 尽管它可能有助于查询今天的值,但可能会损害明天的查询。
关于mysql - 帮助提高查询性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34462780/