如果您的查询或存储过程需要进行性能调整,那么您首先要尝试的是什么?
答案 0 :(得分:114)
以下是我总是给有人询问优化问题的方便清单 我们主要使用Sybase,但大多数建议都将全面适用。
例如,SQL Server附带了许多性能监视/调优位,但是如果你没有这样的东西(甚至可能没有),那么我会考虑以下内容......99%的问题我看到的是因为连接中的表太多。对此的修复是执行连接的一半(使用某些表)并将结果缓存到临时表中。然后在该临时表上继续查询的其余部分。
#temp
表可能比具有大量(数千行)的@table
变量执行得更好。 答案 1 :(得分:19)
答案 2 :(得分:18)
稍微偏离主题,但如果你能控制这些问题......
高水平和高影响力。
答案 3 :(得分:8)
CREATE INDEX
确保您的WHERE
和JOIN
条款有可用的索引。这将极大地加速数据访问。
如果您的环境是数据集市或仓库,那么几乎任何可以想到的查询都应该有索引。
在事务环境中,索引的数量应该更低,并且它们的定义更具战略性,以便索引维护不会拖累资源。 (索引维护是指必须更改索引的叶子以反映基础表中的更改,与INSERT, UPDATE,
和DELETE
操作一样。)
另外,要注意索引中字段的顺序 - 字段越具有选择性(更高基数),它应该出现在索引中越早。例如,假设您正在查询二手车:
SELECT i.make, i.model, i.price
FROM dbo.inventory i
WHERE i.color = 'red'
AND i.price BETWEEN 15000 AND 18000
价格通常具有更高的基数。可能只有几十种颜色可供使用,但可能有数千种不同的要价。
在这些索引选择中,idx01
提供了更快的路径来满足查询:
CREATE INDEX idx01 ON dbo.inventory (price, color)
CREATE INDEX idx02 ON dbo.inventory (color, price)
这是因为更少的汽车会满足价格点而不是颜色选择,这使得查询引擎可以分析更少的数据。
我已经知道有两个非常相似的索引,只是在字段顺序上有所不同,以加快一个中的查询(名字,姓氏)和另一个中的(姓氏,名字)。
答案 4 :(得分:6)
我最近学到的一个技巧是SQL Server可以在更新语句中更新局部变量和字段。
UPDATE table
SET @variable = column = @variable + otherColumn
或者更易阅读的版本:
UPDATE table
SET
@variable = @variable + otherColumn,
column = @variable
我在实现递归计算时使用它来替换复杂的游标/连接,并且在性能方面也获得了很多。
以下详细信息和示例代码对性能进行了极大改进: http://geekswithblogs.net/Rhames/archive/2008/10/28/calculating-running-totals-in-sql-server-2005---the-optimal.aspx
答案 5 :(得分:5)
在这里假设MySQL,使用EXPLAIN来查找查询的内容,确保尽可能高效地使用索引并尝试消除文件排序。 High Performance MySQL: Optimization, Backups, Replication, and More是一本关于此主题的好书,MySQL Performance Blog。
答案 6 :(得分:5)
@Terrapin isnull和coalesce之间还有一些值得一提的差异(除了ANSI合规性,这对我来说很重要)。
答案 7 :(得分:3)
有时在SQL Server中,如果在where子句中使用OR,它将真正地提升性能。而不是使用OR只是做两个选择并将它们联合在一起。以1000倍的速度获得相同的结果。
答案 8 :(得分:2)
使用WITH(NoLock)运行查询是我的标准操作。
。任何人在没有它的情况下捕获了数十GB表上运行的查询。答案 9 :(得分:2)
在我的所有临时表中,我喜欢添加唯一约束(在适当的情况下)来制作索引和主键(几乎总是)。
declare @temp table(
RowID int not null identity(1,1) primary key,
SomeUniqueColumn varchar(25) not null,
SomeNotUniqueColumn varchar(50) null,
unique(SomeUniqueColumn)
)
答案 10 :(得分:2)
第一步:
查看查询执行计划!
TableScan - >坏
NestedLoop - > meh警告
TableScan背后的NestedLoop - > DOOM!
SET STATISTICS IO ON 设置统计时间
答案 11 :(得分:2)
如果可能,将NOT IN查询转换为LEFT OUTER JOINS。例如,如果要查找Table1中Table2中未被外键使用的所有行,则可以执行以下操作:
SELECT *
FROM Table1
WHERE Table1.ID NOT IN (
SELECT Table1ID
FROM Table2)
但是你的表现要好得多:
SELECT Table1.*
FROM Table1
LEFT OUTER JOIN Table2 ON Table1.ID = Table2.Table1ID
WHERE Table2.ID is null
答案 12 :(得分:2)
我通常从连接开始 - 我会逐一将它们中的每一个从查询中删除并重新运行查询以了解是否存在特定的连接我遇到了问题
答案 13 :(得分:2)
查看where子句 - 验证索引的使用/验证没有做任何愚蠢的事情
where SomeComplicatedFunctionOf(table.Column) = @param --silly
答案 14 :(得分:2)
我养成了一直习惯使用绑定变量的习惯。如果RDBMS不缓存SQL语句,那么绑定变量可能无济于事。但是如果你不使用绑定变量,RDBMS就没有机会重用查询执行计划和解析的SQL语句。节省的费用可能很高:http://www.akadia.com/services/ora_bind_variables.html。我主要使用Oracle,但Microsoft SQL Server的工作方式大致相同。
根据我的经验,如果你不知道你是否使用绑定变量,你可能不是。如果您的应用程序语言不支持它们,请找一个。有时,您可以通过对查询B使用绑定变量来修复查询A.
之后,我与DBA联系,了解导致RDBMS最痛苦的原因。请注意,您不应该问“为什么这个查询很慢?”这就像要求你的医生取出你的阑尾。当然你的查询可能是问题所在,但它也可能出现其他问题。作为开发人员,我们倾向于考虑代码行。如果线路很慢,请修复该线路。但是RDBMS是一个非常复杂的系统,你的慢查询可能是一个更大问题的症状。
太多的SQL调优技巧是货物崇拜的偶像。大多数情况下,问题与您使用的语法无关或最低程度相关,因此通常最好使用最干净的语法。然后,您可以开始研究调整数据库(而不是查询)的方法。只有在失败时调整语法。
与任何性能调整一样,始终收集有意义的统计信息。除非是您正在调整的用户体验,否则不要使用挂钟时间。而是查看CPU时间,提取的行和从磁盘读取的块等内容。人们常常为错误的事情做出优化。
答案 15 :(得分:1)
在Sprocs中删除函数调用,其中很多行将调用该函数。
我的同事使用函数调用(从userid获取lastlogindate作为示例)来返回非常广泛的记录集。
任务优化,我用函数的代码替换了sproc中的函数调用:我从>中获得了很多sprocs的运行时间。 20秒到< 1。
答案 16 :(得分:1)
删除任何不必要的游标。
答案 17 :(得分:1)
在SQL Server中,使用nolock指令。它允许select命令完成而无需等待 - 通常是其他事务完成。
SELECT * FROM Orders (nolock) where UserName = 'momma'
答案 18 :(得分:1)
SET NOCOUNT ON
通常是我的存储过程中的第一行,除非我实际需要使用@@ROWCOUNT
。
答案 19 :(得分:1)
我注意:
答案 20 :(得分:1)
确保索引长度尽可能小。这允许DB一次从文件系统读取更多键,从而加快连接速度。我认为这适用于所有数据库,但我知道这是MySQL的具体建议。
答案 21 :(得分:1)
不一定是SQL性能技巧本身但肯定相关:
一个好主意是尽可能使用memcached,因为只需直接从内存中获取预编译数据而不是从数据库中获取它就会快得多。还有一种内置memcached的MySQL(第三方)。
答案 22 :(得分:1)
按您过滤的clm(
)索引表格答案 23 :(得分:1)
@ DavidM
在这里假设MySQL,使用EXPLAIN来查找查询的内容,确保尽可能高效地使用索引......
在SQL Server中,执行计划可以为您提供相同的功能 - 它可以告诉您正在搜索的索引等等。
答案 24 :(得分:0)
答案 25 :(得分:0)
不要使用“sp_”为存储过程名称添加前缀,因为系统过程都以“sp_”开头,并且SQL Server在调用时必须更难以查找过程。
答案 26 :(得分:0)
我喜欢用
isnull(SomeColThatMayBeNull, '')
在
coalesce(SomeColThatMayBeNull, '')
当我不需要coalesce给你的多参数支持时。
http://blog.falafel.com/2006/04/05/SQLServerArcanaISNULLVsCOALESCE.aspx
答案 27 :(得分:0)
答案 28 :(得分:0)
我总是首先使用SQL Profiler(如果它是具有大量嵌套级别的存储过程)或查询执行计划程序(如果它是一些没有嵌套的SQL语句)。有90%的时间可以使用这两种工具中的一种立即找到问题。