从应用程序服务器

时间:2018-01-16 17:56:20

标签: sql sql-server stored-procedures

在尝试优化查询的过程中,我面临着一些奇怪的情况。 在存储过程中,我有这个查询,它返回用户排名:

SELECT @p_rank = COUNT(*) + 1
FROM leaderboard ur
WHERE ur.score > (SELECT ur2.score FROM leaderboard ur2 WHERE ur2.id = @p_id);

基于此查询,我在SP中编写了第二个查询,以按国家/地区获得排名。我已经创建了一个带有国家/地区列的新排行榜表,并尝试了以下查询(基于第一个执行非常好的查询)

SELECT @p_local_rank = COUNT(*) + 1
FROM leaderboard ur
WHERE country = @p_countryand and ur.score > 
(SELECT ur2.score FROM leaderboard ur2 WHERE ur2.id = @p_id);

此查询效果不佳。 我添加了一个国家/地区索引,这没有帮助,但实际上让事情变慢了。 查询处理器建议添加国家/地区索引,其中还包括分数,我尝试了此建议。添加后,查询执行得比所有先前的查询好得多。 我已经更改了SP并在SSMS中对其进行了测试,并且效果非常好。

当我在生产中尝试新的SP时,CPU几乎立即达到 95 +%(通常是 45%)。仅删除此查询会将CPU降低到正常值。 请注意,此SP每分钟执行大约100-150次。

在阅读了很多关于相关问题的问题后,我试图解决这些问题:

  1. 更改了SP以使用本地变量来阻止Parameter sniffing
  2. 清除执行计划缓存。它是一个天蓝色的数据库,所以我使用了ALTER DATABASE SCOPED CONFIGURATION CLEAR PROCEDURE_CACHE;
  3. SET ANSI_NULLS ON;建议here
  4. 使用sp_updatestats
  5. 更新了统计信息

    似乎没有任何帮助,只要我将SP移至生产状态,CPU就会达到95%+。

    表格:

    CREATE TABLE [dbo].[leaderboard](
    [id] [int] NOT NULL,
    [score] [int] NOT NULL CONSTRAINT [df_score_value]  DEFAULT ((100)),
    [level] [int] NOT NULL CONSTRAINT [df_level_value]  DEFAULT ((1)),
    [stage] [int] NOT NULL CONSTRAINT [df_stage_value]  DEFAULT ((1)),
    [insert_date] [datetime] NULL,
    [update_date] [datetime] NULL,
    [daily_score] [int] NOT NULL CONSTRAINT [DF_leaderboard_daily_score]  DEFAULT ((0)),
    [weekly_score] [int] NOT NULL CONSTRAINT [DF_leaderboard_weekly_score]  DEFAULT ((0)),
    [country] [nchar](45) NULL,
    CONSTRAINT [PK_leaderboard] PRIMARY KEY CLUSTERED 
    (
    [id] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
    )
    

    索引位于以下列:

    1. 得分
    2. daily_Score
    3. weekly_score
    4. country INCLUDE得分
    5. 该表包含约300万条记录。

      可以查看执行计划here

      有什么建议可以做什么? `

1 个答案:

答案 0 :(得分:2)

似乎参数和列之间存在一些数据类型不匹配。这在大型数据集上可能非常有问题,因为引擎必须转换每一行的数据,这会导致巨大的性能问题。也可能会有一些参数嗅探,但似乎你已经想到了这一部分。

我还建议为国家/地区添加一个表格,然后在表格中只包含ANSI国家/地区代码。从标准化的角度来看,这会更好。