[英]SQL Primary key sort order
我正在使用MS SQL Server 2005
我有一个3列的表,我存储用户消息映射,如:
msg_for msg_from msg_id
bob bob 1
bob john 1
bob steve 1
bob bob 2
bob john 2
bob bob 3
bob john 3
bob steve 3
PK位于3列,msg_id是存储消息的消息表的FK
以上是我根据3列上的PK看到的物理存储
现在我的查询必须返回顶部有最新消息的给定用户的消息(按msg_id DESC排序)
bob john 3
bob steve 3
bob john 2
bob steve 2
bob john 1
bob steve 1
此映射表具有数百万行。 我看到95%的成本是对结果进行排序。
是否有可能让PK或其他方式存储物理数据(避免SORT)?
msg_for msg_from msg_id
bob bob 3
bob john 3
bob steve 3
bob bob 2
bob john 2
bob bob 1
bob john 1
bob steve 1
谢谢
是。
设置主键(或任何索引)时,您可以定义它
ALTER TABLE dbo.[Messages] ADD CONSTRAINT [PK_Messages] PRIMARY KEY CLUSTERED
(
msg_for ASC, msg_from ASC, msg_id DESC
)
SQL Server可以向任一方向扫描,因此只有在您想要控制多列的排序顺序组合时才有意义。
编辑:您在评论中说问题查询是
select top 10 msg_id
from message_user
where msg_for = @user_name
and msg_from <> @user_name
order by msg_id DESC
这里的问题不是Ascending,Descending。
打个比方。 电话簿以姓氏,姓名顺序列出,但如果您需要知道目录中的字典最后10个名字,则需要扫描整本书。 无论每个部分的名字是否按升序或降序列出,这都是不可避免的。
类似地,复合索引键需要是msg_for, msg_id, msg_from
以最佳地满足此查询而不是msg_for, msg_from, msg_id
对于后一个顺序,它仍然需要扫描满足msg_for = @user_name
标准的索引的整个部分,因为它无法知道以后的msg_id
还会属于后来的msg_from
此外,无论msg_id
在各个子节中的哪个方向排序,对索引的msg_for = @user_name
部分的顺序扫描仍然需要排序,因为它根据msg_from
,它们在子部分中是碎片化的。
保证结果集中顺序的唯一方法是使用ORDER BY。
在SQL Server中,聚簇索引可以帮助...假设优化器将索引视为有用。
难怪排序需要永远。 Varchar / string类型通常是排序时非常繁重的类型,无论是SQL还是任何编程语言。 尽可能使用整体类型来做这些事情。
我建议你使用积分值来识别成员。 有一个Members
表(MemberId INT, MemberName VARCHAR, etc)
,然后是一个Messages
表(MessageId INT, MessageBody VARCHAR, etc)
,然后有一个连接表,比如Correspondence
with (SenderMemberId INT, RecipientMemberId INT, MessageId INT)
。 通过这种方式对积分值进行排序会更快。
我认为您可以轻松地重构数据以适应这种新结构。
根据您的DBMS,您可以使用聚簇索引来实现该目标。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.