繁体   English   中英

SQL主键排序顺序

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM