【问题标题】:What was your coolest SQL optimization, on a slow performing query?在执行缓慢的查询时,您最酷的 SQL 优化是什么?
【发布时间】:2010-10-16 14:20:35
【问题描述】:

刚刚和我的一位同事交谈。在去咖啡机的路上,他步履蹒跚。

我问他“'swarmy' walk 是怎么回事?”,他说,“我刚刚将两个小时的查询缩短到 40 秒!感觉真好”。

他更改了一个使用游标的存储过程并引入了一个临时表,该表是从原始数据集重构的 - 我会尽快给他发电子邮件,以获取有关实际实现的更多信息。

但最终,他在嗡嗡作响。

问题是,什么样的 SQL 会在您的脑海中萦绕不去,让您耳目一新,同时优化执行缓慢的查询?

【问题讨论】:

  • 我很想看看这个长达两小时的查询。

标签: sql performance refactoring


【解决方案1】:

我不得不说我什么时候学会了如何创建和使用覆盖索引。现在,是一个性能提升器。

【讨论】:

  • +1 如果使用得当,可以提供惊人的性能提升
  • 我不知道覆盖索引 - 我刚刚阅读了一篇关于它们的文章,迫不及待地想尝试这种技术! (我是 Ferds 原始问题中“步入正轨的同事”;-))
  • 是的,它们很棒,只是要小心大桌子,因为如果使用不当,它们会变得非常大,而且弊大于利。与所有事物的性能一样,您需要在前后测试具有代表性的工作负载。
【解决方案2】:

使用 SQL 的 BULKIMPORT 将几个小时的继承 INSERT 代码减少到不到一分钟。

【讨论】:

    【解决方案3】:

    采用写得不好的、充满游标的查询并消除游标、将代码减半并多倍地提高性能总是很好的。

    一些最好的改进在于清晰度(通常也会带来不错的性能提升)。

    【讨论】:

    【解决方案4】:

    抱歉,我不太会从这类事情中得到轰动,但大多数情况都是非常基本的,监控查询的性能并添加索引以加快它们的速度。

    现在,通过更改课程中的数据结构和算法来提高我编写的“真实”代码的速度,这就是我获得嗡嗡声的地方(并且被誉为工作中性能修复的最佳人选)。

    【讨论】:

    • 关于嗡嗡声,我同意,当你做久了,感觉就变少了。
    • @Learning,并不是要贬低 SQL,只是它主要由单行查询组成,其中优化相当简单。大型复杂代码库(“真实的”)让我更有成就感。
    • ..ahhh 对于 SQL 中单行查询的日子... :-) 我认为这在很大程度上取决于您在哪里以及您在做什么,但是 SQL 可以变得像“真实”一样复杂' 代码非常快。太快了!
    【解决方案5】:

    嘿,在使用 sqlite 的 iphone 上,通过使用独占写入事务,我立即将数据库处理时间从 40 秒减少到 2 秒...我非常高兴这样做

    因为这是我在嵌入式设备上的第一次 sql 体验 - 与通常的服务器相关内容(索引、规范化等)完全不同

    --- 就服务器而言,索引是真正的祝福。此外,如果您付出一些痛苦并尽可能多地删除表中的空值,您会对性能提升感到惊讶 - 没有多少开发人员专注于空值,他们通常使用索引和其他记录在案的东西

    很少有其他较少被利用的方式 - 使用 xml 一次性处理多个批量插入/更新/删除,而不是一次执行 1 个插入 - 在 sql 2005 中,这可能非常酷

    【讨论】:

      【解决方案6】:

      这都是关于索引的。并避免愚蠢的事情,使他们无用。

      【讨论】:

      • 问题出在键盘和椅子之间!
      【解决方案7】:

      更改 WHERE 子句中条件的顺序,使其首先过滤最具辨别力的条件(同时删除非辨别列中的索引,如性别)。

      【讨论】:

      • 查询优化器应该为你做这件事..这是什么引擎?
      • 您使用的是什么 DBMS?如果您的优化器正常工作,您不需要手动重新排序 WHERE 条件。
      • MS SQL 2000。无论如何,看不到引擎如何优化这一点。如果您想对包含 AND 的某些表达式进行短路评估,您应该编写执行此操作的代码。即使没有短路,如果字段属于同一类型,服务器如何知道哪个字段更具歧视性?
      【解决方案8】:

      过去,我在一个用 COBOL 编写的 CICS/DB2 系统上工作。尽管我们拥有所有正确的索引和WHERE 子句,但我们的许多查询都在进行全表扫描(而且速度很慢)。

      事实证明(我可能有这个倒退,已经 15 年了)问题是我们在WORKING STORAGE 中使用PIC S9(n) COMP 作为查询参数,但DB2 想要PIC S9(n) COMP-3。由于使用了错误的数据类型,DB2 不得不进行全表扫描,以便将数据库中的值转换为我们传入的值。我们更改了变量定义,查询现在能够使用索引,这极大地提高了我们的表现。

      【讨论】:

        【解决方案9】:

        我有一个最初为 SQL Server 6.5 编写的查询,它不支持 SQL 92 连接语法,即

        select foo.baz
        from foo
          left outer join bar
          on foo.a = bar.a
        

        改为写成

        select foo.baz
        from foo, bar
        where foo.a *= bar.a
        

        查询已经有一段时间了,相关数据积累导致查询运行太慢,大约需要 90 秒才能完成。到这个问题出现时,我们已经升级到 SQL Server 7。

        在搞砸了索引和其他复活节彩蛋之后,我将连接语法更改为符合 SQL 92。查询时间降至 3 秒。

        我想我再也不会有那种感觉了。我是一个 f%$^ing 英雄。

        【讨论】:

        • SQL Server 6.5 确实支持左外连接。正如 Ron Soukup(SQL Server 项目经理)所引用的:“在 6.5 版之前,SQL Server 以特殊运算符 = 和 = 的形式提供有限的外连接支持。很多人都假设 LEFT SQL Server 6.5 的 OUTER JOIN 语法只是 *= 的同义词,但事实并非如此。LEFT OUTER JOIN 在语义上与 *= 不同且优于 *=。"
        • 现在这是采用 SQL-92 语法的合理案例。终于!
        【解决方案10】:

        我在上一个问题 ("Biggest performance improvement you’ve had with the smallest change?") 中回答了这个问题,但是,这是一个如此简单的改进,但却经常被忽视,因此值得重复:

        Indexes!

        【讨论】:

          【解决方案11】:

          我们也遇到过类似的情况,我们在 Open Freeway 网站上的查询速度很慢。答案不是优化查询,而是优化它所在的服务器。我们增加了缓存限制和缓存大小,这样服务器就不会那么频繁地运行查询。

          这大大提高了系统的速度,最终让客户满意! :)

          不完全是原帖优化技巧的水准,但绝对让我们热血沸腾!

          【讨论】:

            【解决方案12】:

            将一个非常长的存储过程拆分为一组存储过程,该过程执行了大量“如果在下午 5 点之后,则返回这段 sql”,并且运行时间超过 20 秒一个控制 sp,并将时间缩短到亚秒级响应。

            【讨论】:

              【解决方案13】:

              一个词,动态查询

              如果您使用大量参数进行搜索,您可以将它们从 SQL 字符串中剔除。这大大加快了我的查询速度,而且相对轻松。

              Create PROCEDURE dbo.qryDynamic
              ( 
              
              @txtParameter1 nvarchar(255),
              @txtParameter2 nvarchar(255),
              
              AS
              SELECT     qry_DataFromAView.*
              FROM         qry_DataFromAView
              BEGIN
              
                  DECLARE @SQL nvarchar(2500)
                  DECLARE @txtJoin nvarchar(50)
              
                  Set @txtJoin = ' Where '
              
                  SET @SQL = 'SELECT     qry_DataFromAView.*
                              FROM         qry_DataFromAView'
              
                  IF @txtParameter1 is not null
                  Begin
                      SET @SQL=@SQL + @txtJoin + ' Field1 LIKE N''%'' + @dynParameter1 + N''%'') '
                      Set @txtJoin = ' And '
                  end
              
              
                  IF @txtParameter2 is not null
                  Begin
                      SET @SQL=@SQL + @txtJoin + ' Field2 LIKE N''%'' + @dynParameter2 + N''%'') '
                      Set @txtJoin = ' And '
                  end
              
                  SET @SQL=@SQL + ' ORDER BY Field2'
              
              
                  Exec sp_executesql @SQL, N'@dynParameter1 nvarchar(255), @dynParameter2 nvarchar(255)',  @dynParameter1 = @txtParameter1 ,@dynParameter2 = @txtParameter2
              
              END
              GO
              

              【讨论】:

                【解决方案14】:

                在能够使用交叉表查询来废弃处理和查找的繁琐(技术术语)之后,我有一种温暖的光芒......

                通常这是简单的事情,例如添加索引或只获取您需要的数据,但是当您找到一个适合您以前见过的答案的问题时......好时机!

                【讨论】:

                  【解决方案15】:

                  (话题的一半)

                  我将一个 3000 行的存储过程重写为 LINQ2SQL/C#。 存储过程在一堆未索引的临时表之间处理大量数据。 LINQ2SQL 版本将数据读取到几个字典和 ILookups 中,然后我使用普通的旧 C# 代码手动加入数据。

                  存储过程耗时约 20 秒,LINQ2SQL/C# 版本耗时 0.2 秒。

                  【讨论】:

                    猜你喜欢
                    • 2018-12-12
                    • 2012-08-06
                    • 2010-11-22
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2021-03-06
                    • 2016-12-31
                    相关资源
                    最近更新 更多