Sql server sqlserver中的查询性能

Sql server sqlserver中的查询性能,sql-server,tsql,query-performance,Sql Server,Tsql,Query Performance,我有一个SQL Server表,有超过1100万条记录。这些记录按类别和平台进行组织。我被下面的情景难住了 SELECT COUNT(*) FROM TableName WHERE Category = 'session' AND Platform = 'windows'; -- Returns 1261500 SELECT COUNT(*) FROM TableName WHERE Category = 'session' AND Platform = 'linux'; -- Returns

我有一个SQL Server表,有超过1100万条记录。这些记录按类别和平台进行组织。我被下面的情景难住了

SELECT COUNT(*) FROM TableName WHERE Category = 'session' AND Platform = 'windows';
-- Returns 1261500

SELECT COUNT(*) FROM TableName WHERE Category = 'session' AND Platform = 'linux';
-- Returns 1890599
因此,与“linux”相关的记录比“windows”多60万条

但是,此查询将在6-9秒内返回

SELECT MAX(id) FROM TableName WHERE Category = 'session' AND Platform = 'linux';
然而,这一次我不得不在等待了13分钟之后杀掉

SELECT MAX(id) FROM TableName WHERE Category = 'session' AND Platform = 'windows';
哦。。。我在表中还有以下索引

CREATE NONCLUSTERED INDEX [IX_TableName_CategoryPlatform] ON [dbo].[TableName]
(
    [Platform] ASC,
    [Category] ASC,
    [CreateDate] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
威士忌、探戈、狐步舞

为什么搜索词会有所不同,特别是因为有一个索引

使现代化 我刚才做了如下观察

SELECT MAX(id) FROM TableName WHERE Platform = 'windows';
通过从查询中删除类别,将非常快地返回响应

更新2 我已根据要求创建了两个执行计划。然而,我注意到,由“粘贴计划”实用程序生成的计划中的百分比与我在SSMS中得到的百分比似乎不同,因此我在每个链接下面都包含了我在Management Studio中看到的百分比

对于以下有效的查询

SELECT MAX([MessageID]) [MaxID] FROM [BoothComm].[UniversalMessageQueue] WHERE [MessagePlatform]='windows';
0%:选择 0%:流聚合 0%:顶部 100%:索引扫描 下一个不起作用的查询我只能提供一个估计的执行计划

SELECT 
   MAX(MessageID) AS [MaxID]
FROM BoothComm.UniversalMessageQueue
WHERE 
 MessageCategory = 'session'
 AND
 MessagePlatform = 'windows'
0%:选择 0%:流聚合 0%:顶部 0%:嵌套循环内部联接-为什么会出现这种情况?? 21%:索引扫描 79%:键查找-也是新的,似乎比其他任何东西都要占用更多的时间 谢谢你的帮助

更新3 所以在下面所有的对话和修改之后,我仍然有一个问题

为什么由于将ID添加到索引,此查询在1秒之内返回

SELECT 
      MAX(MessageID) AS [MaxID]
FROM BoothComm.UniversalMessageQueue
WHERE 
    MessagePlatform = 'linux'
    AND
    MessageCategory = 'accounting'
而这一次需要13-22秒来运行

SELECT 
      MAX(MessageID) AS [MaxID]
FROM BoothComm.UniversalMessageQueue
WHERE 
    MessagePlatform = 'windows'
    AND
    MessageCategory = 'accounting'

相同的表、相同的索引、执行计划是绝对相同的。除了MessagePlatform值之外,所有内容都是相同的。与其他记录相比,负责延迟的值出现在更少的记录上

您的查询很慢,因为表没有规范化。您不应该将类别和平台作为字符串存储在每个记录上。相反,它们应该位于具有整数主键的查找表中。然后,这些键将存储在主表中,每个键上都有相应的非聚集索引。然后,您应该将聚集索引添加到列上的主表中,该列按升序排序(最好是唯一的整数)是有意义的


至于您遇到的实际问题,如果没有定义聚集索引,则数据存储在堆中,即未排序的数据堆。您拥有的索引会有所帮助,但性能会受到以下事实的影响:您使用字符串作为键,而且从外观上看,这些字符串不是高度特定的,并且会重复很多次。SQL Server可能只是决定进行完整扫描以回答您的问题,因为它估计这将比任何其他方法都快。

id是您的群集键吗?执行计划显示了什么以及它是否使用了您的索引?如果您将id添加为索引的一个包含项如何?使用以下说明共享您的执行计划:,共享您的表架构。虽然我承认并同意您描述的规范化实践,但此表及时包含快照。问题是引用值可以更改,但这些记录不能更改。因此,虽然5可能比“windows”更有效,但5可能并不总是指“windows”,但此记录必须始终反映“windows”。此外,我在主键中定义了聚集索引。它只是不涉及这个查询。考虑到一个表上只允许有一个聚集索引,未聚集索引是唯一剩下的选项。您可以在查找表中处理更改的历史记录。创建新的查找以向系统添加新值。请务必添加日期戳,以反映更改发生的时间。至于聚集索引,它们用于幕后的每个查询。每个非聚集索引存储聚集键,以便指向原始记录。如果您显示表格定义,这将有所帮助。