我的任务是在工作中优化一些SQL查询。我发现的一切都指向使用解释计划来识别问题区域。我无法确切地找出解释计划告诉我的问题。您将获得成本,基数和字节。
这表明了什么,我应该如何使用它作为指导。低数字更好吗?高更好?任何投入将不胜感激。
或者,如果您有更好的方法来优化查询,我会感兴趣。
答案 0 :(得分:8)
实际上取决于你在做什么,你获得的不仅仅是这些。查看此explain plan页面。我在这里假设您正在使用Oracle并知道如何运行脚本来显示计划输出。开始时可能更重要的是查看左侧是否使用特定索引以及如何使用该索引。如果你正在进行连接,你应该看到像“(Full)”,“(由Index Rowid)”之类的东西。成本将是下一个要考虑的更低成本更好的事情,您会注意到如果您正在进行不使用索引的连接,您可能会获得非常大的成本。您可能还想阅读有关explain plan columns的详细信息。
答案 1 :(得分:7)
我还假设您使用的是Oracle。我还建议你查看解释计划网页,对于初学者。优化有很多,但可以学习。
一些提示如下:
首先,当有人要求你进行优化时,他们几乎总是在寻找可接受的性能而不是最终性能。如果您可以将查询的运行时间从3分钟缩短到3秒,请不要将其减少到2秒,直到系统被要求为止。
其次,快速检查以确保您优化的查询在逻辑上是正确的。这听起来很荒谬,但我无法告诉你我被问及有关慢速运行查询的建议的次数,只是发现它偶尔会给出错误的答案!事实证明,调试查询通常也可以加快速度。
特别是,在解释计划中查找“笛卡尔加入”一词。如果你在那里看到它,那么你发现无意识的笛卡尔加入的可能性非常大。无意的笛卡尔连接的通常模式是FROM子句列出用逗号分隔的表,连接条件在WHERE子句中。除了缺少其中一个连接条件之外,Oracle除了执行笛卡尔连接外别无选择。对于大型表,这是一场性能灾难。
可以在解释计划中看到笛卡尔加入,其中查询在逻辑上是正确的,但我将其与旧版本的Oracle相关联。
还要查找未使用的复合索引。如果查询中未使用复合索引的第一列,则Oracle可能无效地使用索引,或者根本不使用索引。让我举个例子:
查询是:
select * from customers
where
State = @State
and ZipCode = @ZipCode
(DBMS不是Oracle,因此语法不同,我忘记了原始语法)。
快速查看索引会显示带有列的客户索引 (国家,州,ZipCode)按此顺序。我将查询更改为
select * from customers
where Country = @Country
and State = @State
and ZipCode = @ZipCode
现在它运行大约6秒而不是大约6分钟,因为优化器能够使用索引获得良好的优势。我问应用程序员为什么他们从标准中省略了国家,这就是他们的答案:他们知道所有地址的国家都等于'USA',所以他们认为他们可以通过保留该标准来加快查询速度! / p>
不幸的是,优化数据库检索与缩短计算时间的微秒并不完全相同。它涉及了解数据库设计,尤其是索引,并至少概述优化器如何完成其工作。
当你学会与它合作而不是试图超越它时,你通常会从优化器中获得更好的结果。
祝你好运,加快优化速度!
答案 2 :(得分:6)
你得到了棒棒糖的模糊结束。
绝对没有办法,在没有大量额外信息和经验的情况下,查看解释计划并确定哪些(如果有的话)导致性能低于最佳状态。如果查询调整可以简化为10步过程,则可以通过自动化过程完成。我准备列出你需要理解的所有事情才能有效,但这将是一个很长的清单。
我能想到的唯一简短的答案是...寻找计划中的步骤,这些步骤会比您猜测的更多字节。然后考虑如何通过索引或分区来减少这个数字。
说真的,获取Jonathan的Lewis书籍“基于成本的Oracle Fundementals”
获取Tom Kyte关于Oracle数据库架构的书籍,并在树林里租了几个小时。
答案 3 :(得分:4)
这是一个巨大的专业领域(又名黑人艺术)。
我通常采用的方法是:
您需要在要求数据库的上下文中理解不同索引的O()影响。它可以帮助您理解b树,哈希表等数据结构。然后,创建一个可能工作的索引并重复该过程。
如果Oracle决定不使用您的索引,请应用INDEX()提示并查看新计划。成本将高于它选择的计划 - 这就是为什么它没有选择你的指数。暗示的计划可能会让您对您的指数不好的原因有所了解。