Sql 最受欢迎的性能调整技巧

Sql 最受欢迎的性能调整技巧,sql,sql-server,database,performance,Sql,Sql Server,Database,Performance,当您有一个查询或存储过程需要进行性能调整时,您首先要做的事情是什么?查看where子句-验证索引的使用/验证未执行任何愚蠢的操作 where SomeComplicatedFunctionOf(table.Column) = @param --silly 假设这里是MySQL,使用EXPLAIN来了解查询的情况,确保索引被尽可能有效地使用,并尝试消除文件排序。这是一本关于这个话题的好书。@ 假设这里是MySQL,使用EXPLAIN来了解查询的情况,确保索引被尽可能有效地使用 在SQL Serv

当您有一个查询或存储过程需要进行性能调整时,您首先要做的事情是什么?

查看where子句-验证索引的使用/验证未执行任何愚蠢的操作

where SomeComplicatedFunctionOf(table.Column) = @param --silly

假设这里是MySQL,使用EXPLAIN来了解查询的情况,确保索引被尽可能有效地使用,并尝试消除文件排序。这是一本关于这个话题的好书。

@


假设这里是MySQL,使用EXPLAIN来了解查询的情况,确保索引被尽可能有效地使用


在SQL Server中,执行计划会告诉您相同的事情—它会告诉您正在命中哪些索引,等等。

我通常会从连接开始—我会一次一个地将它们从查询中删除,然后重新运行查询,以了解是否存在我遇到问题的特定连接。

通过clm索引表有时,在SQL Server中,如果在where子句中使用OR,它将真正提高性能。而不是使用或只做两个选择并将它们合并在一起。您可以以1000倍的速度获得相同的结果。

这本身不一定是SQL性能技巧,但绝对相关:

一个好主意是尽可能使用memcached,因为直接从内存获取预编译数据比从数据库获取数据要快得多。还有一种MySQL的味道,它内置了memcached(第三方)。

  • 在所有表前面加上dbo。防止重新编译
  • 查看查询计划并搜索表/索引扫描
  • 2005年,在管理视图中搜索缺少的索引

在我所有的临时表上,我喜欢添加唯一的约束(在适当的情况下)来创建索引和主键(几乎总是)


确保索引长度尽可能小。这允许DB一次从文件系统读取更多密钥,从而加快连接速度。我假设这适用于所有数据库,但我知道这是MySQL的一个特定建议

我喜欢使用

isnull(SomeColThatMayBeNull, '')
结束

当我不需要coalesce提供的多参数支持时


不要在存储过程名称前加上“sp_u”前缀,因为系统过程都以“sp_u”开头,SQL Server在调用过程时必须更努力地搜索以找到您的过程。

稍微偏离主题,但如果您能够控制这些问题…
高水平、高影响

  • 对于高IO环境,请确保磁盘用于RAID 10或RAID 0+1或RAID 1和RAID 0的某些嵌套实现
  • 不要使用低于1500K的驱动器
  • 确保磁盘仅用于数据库。即没有日志记录没有操作系统
  • 关闭自动增长或类似功能。让数据库使用预期的所有存储。不一定是目前正在使用的
  • 为类型查询设计架构和索引
  • 如果它是一个日志类型表(仅限insert),并且必须在DB中,则不要为其编制索引
  • 如果您正在分配报告(复杂的选择和许多连接),那么您应该考虑使用星形或雪花模式创建数据仓库
  • 不要害怕复制数据以换取性能
  • 在头脑中对运行查询的最佳路径有很好的了解
  • 检查查询计划-始终
  • 启用STATS,以便可以检查IO和CPU性能。专注于降低这些数字,而不一定是查询时间(因为这可能会受到其他活动、缓存等的影响)
  • 查找输入运算符的行数是否很大,但输出的行数是否很小。通常,索引可以通过限制进入的行数(这可以节省磁盘读取)来提供帮助
  • 首先关注最大的成本子树。更改该子树通常会更改整个查询计划
  • 我看到的常见问题有:
    • 如果有很多联接,有时SQLServer会选择展开联接,然后应用WHERE子句。通常可以通过将WHERE条件移动到JOIN子句中,或将条件内联到派生表中来解决此问题。视图可能会导致相同的问题
    • 次优联接(循环vs散列vs合并)。我的经验法则是,当最上面一行的行数与最下面一行的行数相比非常少时,使用循环联接;当集合大致相等且有序时,使用合并;其他所有行都使用哈希。添加连接提示可以让您测试您的理论
    • 参数嗅探。如果一开始使用不现实的值运行存储过程(例如,用于测试),那么缓存的查询计划可能不适合您的生产值。通过重新编译再次运行应该可以验证这一点。对于一些存储的进程,特别是那些处理大小不同的范围的进程(例如,今天和昨天之间的所有日期-这将需要索引查找-或者,去年和今年之间的所有日期-最好是索引扫描),您可能每次都必须重新编译它
    • 错误的缩进…好吧,Sql Server对此没有问题,但我确实发现,在我修复格式之前,不可能理解查询
  • 我希望:

    • 展开任何游标循环并转换为基于集合的UPDATE/INSERT语句
    • 请注意以下应用程序代码:
      • 调用返回大量记录的SP
      • 然后在应用程序中,遍历每个记录并使用参数调用SP以更新记录
      • 将其转换为在一个事务中完成所有工作的SP
    • 任何执行大量字符串操作的SP。有证据表明数据结构不正确/未标准化
    • 任何重新发明轮子的SP
    • 任何SP,我都无法理解它在一分钟内要做什么
        我已经
        isnull(SomeColThatMayBeNull, '')
        
        coalesce(SomeColThatMayBeNull, '')
        
        SET NOCOUNT ON
        
        set transaction isolation level read uncommitted
        
        SELECT   i.make, i.model, i.price
        FROM     dbo.inventory i
        WHERE    i.color = 'red'
          AND    i.price BETWEEN 15000 AND 18000
        
        CREATE INDEX idx01 ON dbo.inventory (price, color)
        CREATE INDEX idx02 ON dbo.inventory (color, price)
        
        SELECT * FROM Orders (nolock) where UserName = 'momma'
        
        UPDATE table
        SET @variable = column = @variable + otherColumn
        
        UPDATE table
        SET
            @variable = @variable + otherColumn,
            column = @variable
        
        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