【问题标题】:What are your most common sql optimizations?您最常见的 sql 优化是什么?
【发布时间】:2010-11-22 21:32:56
【问题描述】:

您最常用的 SQL 优化是什么?

【问题讨论】:

    标签: sql optimization


    【解决方案1】:

    通过仅返回所需字段和仅返回所需行来减少返回的数据量。这是最常见的,因为您对每个返回数据的查询都执行此操作。

    添加索引。这样做的频率不高,因为有些表不需要为主键创建的索引之外的任何其他索引。

    【讨论】:

    • +1 表示人们容易忘记的明显但非常重要的事实
    【解决方案2】:

    我最喜欢的tips (explained in detail here)列表如下

    1. 尝试使用 WHERE 子句限制查询结果集。
    2. 尝试通过仅返回表中的特定列而不是表的所有列来限制查询结果集。
    3. 使用视图和存储过程而不是繁重的查询。
    4. 尽可能避免使用 SQL Server 游标。
    5. 如果您需要返回总表的行数,您可以使用另一种方法来代替 SELECT COUNT(*) 语句。
    6. 尽可能使用约束而不是触发器。
    7. 使用表变量而不是临时表。
    8. 尽可能避免使用 HAVING 子句。
    9. 尽可能避免使用 DISTINCT 子句。
    10. 在存储过程中包含 SET NOCOUNT ON 语句,以停止指示受 T-SQL 语句影响的行数的消息。
    11. 如果只需要返回前 n 行,请使用带有 TOP 关键字的 select 语句或 SET ROWCOUNT 语句。
    12. 如果您需要快速返回“number_rows”行,请使用 FAST number_rows 表提示。
    13. 尽可能使用 UNION ALL 语句而不是 UNION。
    14. 不要在查询中使用优化器提示。

    【讨论】:

    • 不确定视图而不是繁重的查询是什么意思。由于视图只是一个存储的子查询,除了易于阅读之外,它应该没有任何区别。此外,如果您的解决方案需要,可以使用 HAVING 子句。
    • Rob 使用视图而不是重型查询,可以减少网络流量,因为您的客户端将仅向服务器发送存储过程或视图名称而不是大型重型查询文本。这也可以用来促进权限管理,因为您可以限制用户访问他们不应该看到的表列。
    • 啊 - 所以它更像是“当您可以查询视图或使用存储过程时,不要使用临时查询”。当然,我同意...
    • Rob,一个例子可能是 16k 的子查询,会在 16K 时使网络过载,而运行视图会占用几个字节的带宽。
    • 是的,当然。使用应用程序中的存储过程绝对值得。
    【解决方案3】:

    到目前为止:制作覆盖索引

    覆盖索引包括查询所需的所有列,从而避免了对索引查找结果进行查找的需要。这将避免系统感觉扫描可能更快(考虑到查找成本,这非常快)。

    但也值得一提:

    有一个允许合并连接的索引。当连接两个按连接条件排序的表时,可以发生 MERGE 连接。但是,当然,在说“表”时,我们真正的意思是“索引”,对吧……

    另外 - 删除标量函数并改用表值函数...因为标量函数无法简化。

    另外 - 将唯一索引放在您知道是唯一的列上,允许查询优化器使用此知识来做出更好的优化选择。也适用于 NOT NULL 约束。

    另外 - 在比较已知大小写的字符串时使用二进制排序规则,这样系统就不必考虑不同的大小写选项。

    当然我可以继续一整天...

    罗伯

    【讨论】:

    • 值得指出的是,标量函数可能是 SQL Server 本地的。但其他的则跨越大多数数据库系统。
    • :) 谢谢 RRUZ。查询覆盖索引绝对值得,因为它们可以使查询运行速度提高数千倍。
    【解决方案4】:

    缓存数据库输出。完全避免对数据库施加压力似乎是一种谨慎的优化。

    +1 内存缓存。

    【讨论】:

      【解决方案5】:

      索引外键!

      也许这不是 sql 查询语法优化,而是存储优化。但我看到它一直在重复发生,这是一个令人讨厌的问题。

      【讨论】:

        【解决方案6】:

        1) 我还没有找到一种情况

        SELECT Field1, Field2, (SELECT Count(*) FROM tblLinked WHERE tblLinked.Field3 = tblSource.Field3) AS TheTotal
        FROM tblSource
        

        不通过 LEFT JOIN 对派生表进行改进。

        SELECT Field1, Field2, IsNull(Linked.TheTotal,0) AS TheTotal
        FROM tblSource
        LEFT JOIN (SELECT Field3, Count(*) AS TheTotal
            FROM tblLinked
            GROUP BY Field3) AS Linked ON tblSource.Field3 = Linked.Field3
        

        2) 不要在服务器上对结果进行排序,除非消费应用程序本身无法执行此操作。这不太适用于 Web 应用程序,但对于桌面应用程序,客户端 PC 通常有足够的可用功率并且可以愉快地进行排序。

        3) 使用 EXISTS 而不是检查匹配条目的计数。

        4) 不要沉迷于只在一个 SELECT 子句中执行查询。明智地使用表变量(有时是临时表)可以大大减少处理的行数。

        【讨论】:

        • Re 1)... 应该以同样的方式对待。您使用的是什么 DBMS?
        • SQL 服务器。根据我的经验,子选择的运行速度比使用派生表的查询慢得多。
        【解决方案7】:

        我使用 SQL 进行过的最佳优化是真正了解需要对数据执行什么操作并从查询中删除大量 SQL。

        最快的查询是不必运行的查询。

        认真考虑您对数据所做的工作。你在逐行工作吗? (然后使用基于集合的代码)。

        • 您真的需要加入所有这些表吗?

        • 两个小(简单)查询能否比单个大查询更好更快地完成这项工作?

        • 如果将这两个查询合并到一个查询中,它会运行得更快吗?

        最后,PROFILE 查询(EXPLAIN PLAN 或 SQL PROFILER)并查看“IO 获取”。通常,您希望将 GET 的数量减少到每个输出行 10 个的比率。

        【讨论】:

          【解决方案8】:

          降低事务隔离级别以绕过用户查询的表锁。并非一直如此,但对于 gui 显示一般信息来说效果很好。

          【讨论】:

            【解决方案9】:

            如果你说的是普通话,那么索引是我脑海中第一个跳出来的东西。

            它们是一种经常被误解和滥用的强大技术。

            然后我会进行反规范化,这可以为许多数据库增加相当多的性能。

            查询优化排在第三位,它也很有帮助。这些天我使用 MySQL,查询日志记录对优化有很大帮助。

            Memcached 绝对不常见,尽管在脚本端(ASP.Net 或 PHP)是许多网站的一部分(ASP.Net 或 PHP)。

            【讨论】:

              【解决方案10】:

              确保表以正确的顺序连接。

              【讨论】:

              • 数据库引擎不会自动执行此操作吗?!我一直认为他们在执行之前对查询进行了重新排序......
              • 是的。对于 Sybase ASE,优化器将尝试根据查询的成本选择最佳连接顺序。通常(如果统计数据是最新的)它将以正确的顺序加入。但是我见过很多连接顺序没有正确输出的例子。此外,如果您有大量表,查询中的表顺序可能会有所不同,因为 DBMS 通常一次考虑 x 个表排列。我总是尝试按照我希望它们加入的顺序列出我的表(如果你需要强制加入顺序也很方便)。
              【解决方案11】:

              根据我的经验,最重要的两件事是更少的连接和更少的查询。除了那些有很多特定于 DB 的东西之外,COUNT(*) 在 PgSQL 上相对较慢,子选择在 MySQL 上很慢,等等。

              【讨论】:

                【解决方案12】:

                我最近使用的最大优化非常简单。

                让尽可能多的业务逻辑尽可能靠近 sql server。 Aka 将您的业务代码与 sql 服务器放在同一台机器上。让您的业务逻辑尽可能少地将代码返回给最终客户端。

                像 Frost 所说的那样,让您的 SQL 查询“尽可能短”,在多个语句上使用单个更新语句。

                仅在需要时使用事务

                为部分连接创建临时表以加速连接(不要忘记为它们建立索引)

                【讨论】:

                  【解决方案13】:

                  我已阅读所有答案,但没有找到 LIMIT 和 OFFSET 使用提示。在带有“prev”和“next”链接的分页中非常常见。但是渲染这样的显示会比站点的整个其余部分消耗更多的资源。当偏移大量项目时,查询会变得非常慢。所以避免这些查询。

                  • 不计算总项目数。
                  • 仅显示前“n”个项目(例如仅前 100 个)。

                  此类方法使用 Google、Twitter 和其他网站。在 Google 搜索中,没有准确的结果数量。只有大概的数字。 Twitter 不允许用户查看所有过去的推文。它只显示最后 n 个数字(我不记得有多少)。

                  有一些link from MySQL performance blog

                  【讨论】:

                    【解决方案14】:
                    1. 索引其最常见的优化
                    2. 对表格进行反规范化。
                    3. 消除约束(仅当您知道自己在做什么时)

                    【讨论】:

                    • 移除约束是一件很有趣的事情。它可以帮助执行更改,但会损害查询的性能。
                    • 约束被 sql 引擎用来获得最优化的查询计划,然后删除可能会导致性能损失,正如 Rob 指出的那样。
                    • 我认为在进行大量插入时删除约束会有所帮助。
                    • 反规范化表并不总是能推动优化。例如,如果您将结果集(我们可以称之为缓存数据)保存在某个表中。数据不会自动归一化,但您可以实现更好的系统性能。
                    【解决方案15】:

                    避免在视图中使用板载函数,如 convertdate、stringreplace 等。 如果您不能确保数据的格式有效,请使用运行的存储过程 定期“清理”相关表中的数据。

                    这很讨厌,但它节省了观看时间,即让用户开心... ^^

                    【讨论】:

                      【解决方案16】:

                      几个提示: 使用

                      delete from table where id>=1 and id<=3;
                      

                      而不是

                      delete from table where id=1;
                      delete from table where id=2;
                      delete from table where id=3;
                      

                      也使用 'IN' 而不是 'OR' 语法

                      【讨论】:

                      • 怎么样:从 id 介于 1 和 3 之间的表中删除 - 看起来更加简洁
                      • 是的,也许吧,但想法是:不要使用循环查询。
                      【解决方案17】:

                      不需要的就不要放约束,因为约束会增加一个索引,索引越多,插入数据的时间就越长。

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 2010-10-16
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2010-10-02
                        • 1970-01-01
                        • 1970-01-01
                        • 2021-04-20
                        相关资源
                        最近更新 更多