Sql Server 查询性能

Posted

技术标签:

【中文标题】Sql Server 查询性能【英文标题】:Sql Server query performance 【发布时间】:2010-05-07 11:18:14 【问题描述】:

我在一个繁忙的数据库上有一个存储过程,它经常在昂贵的查询列表中名列前茅(以某种方式)。查询非常简单,它采用单个参数(@ID,int)作为表的主键,并选择与该 ID 匹配的记录。主键是一个带有聚集索引的标识字段,所以我不知道如何进一步优化它?

查询如下

CREATE PROCEDURE [dbo].[P_Call_Get]

    @ID int = null

AS

    select ID,
        AppID,
        AgentID,
        AgentLogin,
        Ext,
        VDN,
        VDNName,
        Skill,
        SkillName,
        CallFrom,
        TelNoFrom,
        ParentCallID,
        CallStart,
        ACWStart,
        CallEnd,
        Outcome,
        StageID,
        TxTo,
        TxSuccess,
        ServiceID,
        DiallerID,
        CRC,
        TSCallID,
        CallDirection,
        [Manual],
        CallBackAgent,
        CallBackDateTime,
        Notes
    from P_Call
    where (ID = @ID or @ID is null)

不确定发布执行计划的最佳方式 - 它显示的只是 100% 的操作被聚集索引扫描占用

【问题讨论】:

你能把代码贴出来吗? 你能发布查询和执行计划吗? 当你说它是最昂贵的时候,它做了多少次读取?多久调用一次? 会不会因为使用频率高而显得最贵?如果它执行 10 个逻辑 I/O 但每天运行 10,000,000 次,它可能看起来很昂贵,但实际上它可能没问题。 它被称为很多!呼叫中心的每个座席每次呼叫至少会呼叫一次,每天有 100 个座席接听 3 - 400 个呼叫 【参考方案1】:

我认为通过使用where (ID = @ID or @ID is null),您将获得一个次优计划。将其划分为 2 个单独的查询,以便在 @Id 不为空的情况下,它只会直接查找它,您将在计划中出现搜索而不是扫描。您也许可以创建一个包含避免重复所需的列的视图(即没有任何 where 子句的查询)

select ID,
    AppID,
    AgentID,
    AgentLogin,
    Ext,
    VDN,
    VDNName,
    Skill,
    SkillName,
    CallFrom,
    TelNoFrom,
    ParentCallID,
    CallStart,
    ACWStart,
    CallEnd,
    Outcome,
    StageID,
    TxTo,
    TxSuccess,
    ServiceID,
    DiallerID,
    CRC,
    TSCallID,
    CallDirection,
    [Manual],
    CallBackAgent,
    CallBackDateTime,
    Notes
from P_Call

【讨论】:

分割成 2 个查询正是这样做的——我现在在我的执行计划中得到一个搜索而不是扫描。这让我有点害怕,因为我在许多搜索多个可选标准的 SP 中使用了这种方法。本来想问一个更好的方法,但我认为优化这些是一个单独的问题 我不确定是否有任何方法可以解决拆分为 2 个查询的方法。让复杂的查询保持同步可能有点麻烦,尤其是当您对查询中的多个参数使用这种方法时。 @Macros 无法避免拆分 - SQL 服务器通常只为每个语句维护一个执行计划。【参考方案2】:

尝试清理过程缓存和内存缓冲区:

DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE

在测试过程性能之前这样做会阻止使用缓存的执行计划和以前的结果缓存。

【讨论】:

【参考方案3】:

你可以使用表格分区吗?它可能会解决问题。

【讨论】:

【参考方案4】:

表中有多少行?您确实意识到“聚集索引扫描”= 全表扫描。

【讨论】:

我没有……但现在就去做!在过去的 2 天里,基于此优化了 SP 好交易。您可能已经弄清楚了原因,但我应该已经解释了优化器选择次优计划的原因。不能使用索引的原因是 WHERE 子句的(或@ID 为空)部分。 NULL 值不被索引。

以上是关于Sql Server 查询性能的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 性能查询

SQL Server 中的查询性能

大型sql server查询性能优化

Sql Server 查询性能

WHERE 子句中的 OR 会降低 sql 查询性能(sql server)

SQL Server 查询性能优化——创建索引原则