在尝试优化查询的过程中,我面临着一些奇怪的情况。 在存储过程中,我有这个查询,它返回用户排名:
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次。
在阅读了很多关于相关问题的问题后,我试图解决这些问题:
ALTER DATABASE SCOPED CONFIGURATION CLEAR PROCEDURE_CACHE;
sp_updatestats
似乎没有任何帮助,只要我将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)
)
索引位于以下列:
该表包含约300万条记录。
可以查看执行计划here
有什么建议可以做什么? `
答案 0 :(得分:2)
似乎参数和列之间存在一些数据类型不匹配。这在大型数据集上可能非常有问题,因为引擎必须转换每一行的数据,这会导致巨大的性能问题。也可能会有一些参数嗅探,但似乎你已经想到了这一部分。
我还建议为国家/地区添加一个表格,然后在表格中只包含ANSI国家/地区代码。从标准化的角度来看,这会更好。