【问题标题】:How far does optimization in sql queries go?sql查询中的优化能走多远?
【发布时间】:2013-02-25 19:31:46
【问题描述】:

我的背景是应用程序编程,并且有一条指导方针说不要试图“超越”编译器,例如JIT 等在优化方面。
SQL 查询也是这种情况吗?
我的意思是我已经读到 SQL 服务器为预期是最佳的查询(对吗?)执行某种执行计划,但是是否重新排列/修改实际查询?
还是希望程序员确保查询是最优的?例如。先选择然后join

【问题讨论】:

  • 你用的是什么数据库?
  • @Narnian:我的问题是一般性的,而不是特定于特定数据库。如果重要的话,我正在使用MSMySQL

标签: sql performance optimization query-optimization qsqlquery


【解决方案1】:

我的经历(包括为数据库服务器供应商工作)如下。

首先,数据库已经过高度优化,并编译为机器代码(通常用 C 或 C++ 编写)。在现代设备上,大多数操作都非常快,以至于不会注意到次优的执行。

但是,有一些地方需要注意。

如果您没有索引,那么数据库必须进行表扫描,这可能会很慢。许多人只将一个字段放入索引中,但您应该在应用时考虑多个字段。解释实用程序可以向您显示它找到的索引,并建议哪些索引会有所帮助。

共同相关的查询可能很慢。此外,当您有一个带有表达式的 where 子句时,数据库必须为每条记录评估它,并且不能使用索引。

打开连接很慢,所以一定要重复使用连接,而不是每次操作都重新打开。

然而,当今最大的问题通常是数据库客户端和数据库服务器之间的网络通信。尽量减少网络转向数据库,并让数据库过滤结果,从而减少需要通过网络发送的数据。

【讨论】:

  • On modern equipment most operations are so fast, that sub-optimal execution won't be noticed但这不取决于数据的大小吗?
  • 这里我是说八核 2 Ghertz 处理器可以在几分之一秒内处理数十万条记录。用户无法分辨 1/30 秒或 1/10,000 秒返回结果之间的区别。很多人只为一个字段建立索引而错过了一个索引中多个字段的优化,但数据库似乎并不慢,所以他们不在乎。
【解决方案2】:

有些事情你想让数据库做,有些事情只有人才能做。数据库管理不能留给数据库本身。人必须参与。

数据库优化既是一门艺术,也是一门科学。数据库通过从已创建的索引中选择最佳索引,在优化查询方面做得很好。但是,数据库不会自动创建最佳索引。确定最佳索引是 DBA/程序员的工作。

索引可能会使查询变得非常快,但它可能需要 1 GB 的内存。这不是您通常要添加的索引。但是,人们可以查看查询,并意识到只需稍微重新格式化查询即可。

了解数据本身的开发人员有能力就使用哪些索引等做出正确的决定。查看您的索引以查看其中一些是否正在使用也很好。有时会创建索引但数据库从未使用过,因为不同的索引总是更好,或者永远不会运行需要索引的搜索。

因此,数据库根据已有的索引就如何最有效地运行查询做出了重大决策,但我们的工作是分析数据库是否具有正确的索引并采取适当的措施。

【讨论】:

    【解决方案3】:

    总的来说,建议是好的。创建优化引擎所需的开发人员年数比您要管理的要多得多。

    也就是说,每个数据库肯定都存在缺陷。在某些情况下,您需要以某种方式表达某些逻辑,以使其更有效率。或者,您可能需要添加提示以获得正确的执行路径。

    这是因为 SQL 的优化通常比其他语言的优化困难得多。它需要了解数据和值的分布才能得出最佳解决方案。

    我的建议是以最能表达您想要完成的内容的方式编写查询,并使用传达查询目的的命名约定和缩进来编写它们。这样,如果您确实必须修改查询,您至少会了解它在做什么。

    【讨论】:

    • 只是吹毛求疵,其他语言的出色优化还关键取决于理解数据以及哪些是频繁的,哪些不是。通常,编译器甚至不会尝试这样做,除非更有效地实现某些众所周知的语言功能的特殊情况(并且通常只是通过一个常数因素)。提高渐近复杂度的大规模程序转换至少对于传统编程语言和关系模型一样困难。可能更难。
    • @delnan 。 . .我不会不同意这一点。我的印象是,这个问题更多的是关于典型的优化类型,而不是系统优化。实际上,从这个角度来看,每个 SQL 查询都是对某种系统优化的尝试——并且需要考虑可用内存、磁盘和处理器。
    【解决方案4】:

    在某些情况下,您自己的知识会派上用场。以下是一些示例。

    1 - 你想要这个月的一切。这很简单

    where Year(datefield) = 2013
    and month(datefield) = 'February'
    

    但这会跑得更快

    where datefield >= '2013-02-01'
    and datefield < '2013-03-01'
    

    2 - 你想要男孩叫帕特。性别被索引,名字没有。这更快

    where sex = 'M'
    and name = 'Pat'
    

    比这个

    where name = 'Pat'
    and sex = 'M'
    

    3 - 在案例结构中,首先列出最常发生的情况。这个

    case when something that almost always happens then 'yes' else 'no' end
    

    会跑得比

    case when something that almost never happens then 'no' else 'yes' end
    

    【讨论】:

    • 对于(1),我可以想到反例。 (2) 在我知道的任何数据库中都是错误的。 where 子句中简单条件的顺序不会影响索引的使用(有些数据库甚至不会使用性索引,因为无论如何这都是个坏主意)。第三种完全是假的,因为有一个条件,所以判断它是真还是假需要相同的时间。
    • 不确定其他 2 个,但为什么 1 会更好?
    • 对于 1,我在 Oracle 数据库中进行了个人观察,其中在 where 子句中使用函数会导致查询运行速度变慢。有问题的函数是 trunc。
    猜你喜欢
    • 2013-07-02
    • 1970-01-01
    • 1970-01-01
    • 2011-01-20
    • 1970-01-01
    • 2017-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多