概述:
我有一个构建查询语句的系统。其中一些必须根据传递给系统的set参数将一些表连接到其他表。在对创建的查询运行一些性能测试时,我注意到有些查询正在进行FULL TABLE SCANS,在很多情况下,我读过的内容对大表不利。
我想做的事:
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秒之间。
2 - Advisor显示多个警告,其中一些警告与全表扫描和索引有关。
问题:
假设所有索引都可用并创建
1 - 有更好的方法来执行此查询吗?
2 - 加入的连接数是多少?
3 - 连接可能是问题吗?
4 - 问题是否在WHERE子句中?
5 - 我可以错过什么优化技术/工具?
6 - 如何让此查询以0.0008和0.0001之间的速度执行?
如果需要图像和视觉效果来帮助澄清我的情况,请在下面的评论中提问。我感谢任何和所有的帮助。
谢谢=)
答案 0 :(得分:1)
" p_id_one"并没有告诉我们多少。这是auto_increment吗?真正的列名有时会提供重要的基数和意图线索。正如威廉所说,"这个问题必须有更多的问题"和"整体问题是什么"。
LEFT
- 你需要吗?它阻止了某些形式的优化;如果'右边'表行不是可选的。
WHERE a.p_id_one = 1234567890
需要INDEX(p_id_one)
。那是PRIMARY KEY
吗?在这种情况下,不需要额外的INDEX
。 (请提供SHOW CREATE TABLE
。)
那些列/表达式真的是SELECTing
吗?它可以有所作为 - 特别是当建议覆盖索引时#34;作为优化。
请提供EXPLAIN SELECT ...
的输出(这不是您提供的讨论。)该输出将有助于提供1:许多,基数等的线索。
如果这些是FOREIGN KEYs
,则您已经在b.fk_id_one上有索引,c.fk_id_two,d.fk_id_two;所以那里没什么可做的。
1.6ms是涉及4个表的查询的绝佳时间。不要计划大幅加快速度。您可能每秒处理数百个连接,执行数千个类似的查询。你还需要更多吗?
您使用的是InnoDB吗?这在并发访问方面更好。
您的示例似乎没有任何全表扫描;请提供一个例子。
10行表中的 ALL
无需担心。在一百万行的桌子上,这是一个大问题。你的桌子会显着增长吗?在担心ALL
时,您应该注意这一点:全表扫描有时更快比使用完美'指数。当估计的行数超过表的约20%时,优化器决定扫描。表扫描是有效的,因为它直接扫描表,即使跳过80%的行。使用索引更复杂 - 扫描索引,但对于索引中找到的每一行,需要在数据中查找以查找行。如果您认为自己不应该看到ALL
,那么可能索引的选择性不是很高。别担心。
不要使用FORCE INDEX
- 虽然它可能会有助于查询今天的价值,但明天的查询可能会受到影响。