协助提高查询的性能

时间:2015-12-25 12:18:58

标签: mysql sql left-join query-optimization query-performance

概述

我有一个构建查询语句的系统。其中一些必须根据传递给系统的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

The Explain

查询时间

Showing rows 0 - 10 (11 total, Query took 0.0016 seconds.)

当前问题

1 - 我的系统/ DBMS(phpmyadmin)的查询时间介于0.0013秒和0.0017秒之间。

  • 我做了什么修理?
    全表扫描或“全部”扫描类型查询正在表格上运行(' BTable',' DTable')所以我尝试在适当的ID上使用FORCE INDEX。 使用FORCE INDEX会删除全表扫描,但它不会加速 性能。 我仔细检查了我的fk_constraints和索引关系,以确保我没有遗漏任何东西。到目前为止,一切都结束了。

2 - Advisor显示多个警告,其中一些警告与全表扫描和索引有关。

问题

假设所有索引都可用并创建

1 - 有更好的方法来执行此查询吗?

2 - 加入的连接数是多少?

3 - 连接可能是问题吗?

4 - 问题是否在WHERE子句中?

5 - 我可以错过什么优化技术/工具?

6 - 如何让此查询以0.0008和0.0001之间的速度执行?

如果需要图像和视觉效果来帮助澄清我的情况,请在下面的评论中提问。我感谢任何和所有的帮助。

谢谢=)

1 个答案:

答案 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 - 虽然它可能会有助于查询今天的价值,但明天的查询可能会受到影响。

相关问题