帮助提高查询的性能

Posted

技术标签:

【中文标题】帮助提高查询的性能【英文标题】:Assistance in Improving a query's performace 【发布时间】:2015-12-25 12:18:58 【问题描述】:

概述

我有一个构建查询语句的系统。其中一些必须根据传递到系统的设置参数将一些表连接到其他表。在对创建的查询运行一些性能测试时,我注意到一些查询正在执行 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 秒之间。

我做了哪些修复工作? 全表扫描或“ALL”类型的查询正在表(“BTable”、“DTable”)上运行,所以我尝试在适当的 id 上使用 FORCE INDEX。 使用 FORCE INDEX 会删除全表扫描,但不会加快 表现。 我仔细检查了我的 fk_constraints 和索引关系,以确保我没有遗漏任何东西。到目前为止,一切都已验证完毕。

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

问题

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

1 - 有没有更好的方法来执行这个查询?

2 - 多少个连接是太多连接?

3 - 连接可能是问题吗?

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

5 - 我可能错过了哪些优化技术/工具?

6 - 我怎样才能让这个查询以 0.0008 和 0.0001 之间的速度执行?

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

谢谢你=)

【问题讨论】:

我认为查询没有更好的选择 请发布EXPLAIN 输出。 我已将解释添加到问题中,请查看谢谢。 如果 0.0017s 对你来说太慢了,这个问题肯定不止这个查询。请为您尝试解决的整体问题提供上下文,以便我们理解您为什么需要此查询低于 0.001 秒。很可能我们将能够更好地帮助解决整体问题,而不是试图进一步压缩这个已经超快的查询。 我将深入研究我在这个问题中可能遗漏的所有上下文片段,并在编辑后的更新中发布。 【参考方案1】:

“p_id_one”并没有告诉我们太多。这是一个自动增量吗?真实的列名有时会提供重要的基数和意图线索。正如威廉所说,“这个问题肯定还有更多”和“整体问题是什么”。

LEFT -- 你需要吗?它阻止了某些形式的优化;如果“右”表行不是可选的,则将其删除。

WHERE a.p_id_one = 1234567890 需要INDEX(p_id_one)。已经是PRIMARY KEY 了吗?在这种情况下,不需要额外的INDEX。 (请提供SHOW CREATE TABLE。)

那些真的是你SELECTing的列/表达式吗?它可以有所作为——尤其是在建议将“覆盖索引”作为优化时。

请提供EXPLAIN SELECT ... 的输出(这不是您提供的讨论。)该输出将有助于提供 1:many、基数等线索。

如果这些是FOREIGN KEYs,则您已经在 b.fk_id_one、c.fk_id_two、d.fk_id_two 上有索引;所以这没什么好做的了。

1.6ms 是涉及 4 个表的查询的绝佳时间。不要计划显着加快速度。您可能会处理数百个连接,每秒执行数千个类似查询。您还需要更多吗?

你在使用 InnoDB 吗?这更适合并发访问。

您的示例似乎没有任何全表扫描;请提供一个例子。

ALL 在 10 行表上无需担心。在百万行的桌子上,这是一件大事。你的桌子会显着增长吗?当担心ALL 时,您应该注意这一点:全表扫描有时比使用“完美”索引更快。当估计的行数超过表的大约 20% 时,优化器决定扫描。表扫描是高效的,因为它直接扫描整个表,即使跳过了 80% 的行。使用索引更复杂——扫描索引,但是对于在索引中找到的每一行,都需要查找数据以找到该行。如果您认为不应该看到ALL,那么可能该索引不是很有选择性。别担心。

不要使用FORCE INDEX——尽管它可能有助于查询今天的值,但可能会损害明天的查询。

【讨论】:

选择的列不是实际的列。它们是虚拟字段,旨在大致了解我正在使用的内容。但是 SQL 和 EXPLAIN 与实际查询非常相似。解释是解释图像的链接。由于我在 *** 上的声誉不是 15,因此我无法在此处发布实际图像。 p_id_one 是主 id 键,因为 fk_id_one 是外键。尽管人们说 1.6 毫秒非常好,但我只是想看看是否有更好的解决方案。创新数据库?当然。通过 FORCE INDEX 删除了全表扫描。 表格将显着增长,所以我现在需要我的数据库尽可能快,以便随着时间的推移保持这种状态。 每张表有多少行?也许这些表太小了,完全扫描与使用索引的对比可能会随着大小而消失。 EXPLAIN 表示一切运行良好。您可能有不必要的担忧。 目前每个表有0行。但是,使用插入了 30,000 个虚拟行的类似查询运行基准测试表明查询时间没有太大变化。我将对每个表中的 100,000 行进行基准测试,看看它是如何工作的,然后发布我的结果,看看是否需要进行任何微调和调整。正如您所说,今天的查询可能会损害明天的查询。那么为什么不试运行它以找出虚拟数据。 在进行基准测试时请记住,由于缓存,第一次运行可能会变慢。 0 行对于计时毫无用处。 30K 和 100K 可能会相似。 30K 行是 1.6ms 吗?这是唯一有趣的查询吗?

以上是关于帮助提高查询的性能的主要内容,如果未能解决你的问题,请参考以下文章

需要帮助来提高一些 TSQL“不存在”的查询性能

需要帮助来提高 MYSQL 子查询性能

提高查询性能mongodb

如何使用许多 JOIN 提高查询性能

如何提高风数据SQL查询性能

如何提高大型表上基于日期的查询性能?