SQL Server 2005:哪个更快?条件超过 2 列或超过 2 行?
Posted
技术标签:
【中文标题】SQL Server 2005:哪个更快?条件超过 2 列或超过 2 行?【英文标题】:SQL Server 2005: which one is faster? Condition over 2 columns or over 2 rows? 【发布时间】:2010-02-09 22:17:24 【问题描述】:Table1
------------
ID
IdColumn1
Idcolumn2
Table2
------------
ID
IdColumn
IdPair
它们都包含相同的数据。
Table1 填充了两列,Table2 将这些列存储在两行中。
所以,如果 Table1 包含 n 行,Table2 将有 2 * n 行
哪个查询更快?
select * from Table1
where IdColumn1 = x or IdColumn2 = x
或
select * from Table2 where IdColumn = x
我已经选择了 Table2 方案,到目前为止,我有超过 400.000 行,每天有超过 1000 个独立访问者。每天在此数据库中添加超过 2000 行。我的网站保持快速增长。
别问我为什么有这么多排,他们玩的是在线比赛,那些排是玩家之间的比赛。
【问题讨论】:
【参考方案1】:我也会选择 Table2。
为了强调方法的区别,这里是为选项生成的 3 个执行计划,假设 Table1 在 IdColumn1 和 IdColumn2 上具有非聚集索引,并且 Table2 在 IdColumn 上具有非聚集索引。 ID 是集群的。 Table1 100,000 条记录,Table2 200,000 条记录
1) Table1 方法在 2 个 id 列上使用 OR 条件:alt text http://img52.imageshack.us/img52/3264/23430147.png
2) 使用 2 个语句与 UNION ALL 相结合的 Table1 方法:alt text http://img192.imageshack.us/img192/6281/47968640.png
3) Table2 方法:alt text http://img52.imageshack.us/img52/2131/72286216.png
Table2的方案显然要简单很多。
【讨论】:
Table1的第一个方案其实很有意思,看看OR是怎么变成MergeJoin和StreamAggregate的?优化器非常聪明!【参考方案2】:我会选择 Table2。
使用 Table1 架构,您至少需要两个索引,一个在 IdColumn1 上,一个在 IdColumn2 上,您可以使用以下方法高效地查询它:
select * from Table1 where IdColumn1 = x
union all
select * from Table1 where IdColumn2 = x;
但至少有一个索引是非聚集的,并且您将有大量的逻辑杂耍来识别与玩家相关的所有项目,因为它们可以位于 IdColumn1 或 IdColumn2 上。想想未来三路游戏会带来的混乱(3 名玩家,添加 IdColumn3...)。
Table2 更好,因为它有一个明确的目的:存储玩家参与过的所有游戏,按玩家 ID 进行聚类。它可以被更简单地询问,可以更简单地构建,并且可以在以后每场比赛扩展到更多玩家。
虽然不确定 PairId 是什么。您的数据模型是典型的多对多关系,只需将 'Player' 替换为 'Student' 和 'Game' 替换为 'Course' ,您会发现您完全符合 Student-Course 的规范 Data Modeling 101 课程结构(在您的情况下,游戏(=课程)恰好可以有2个玩家(=学生),但这是一个细节。您仍在谈论典型的3桌关系(1个用于游戏,1个用于玩家,一个用于玩家对游戏的参与)。
【讨论】:
IdPair 是用来标识 Opponent 行。如果我与其他人匹配,那么我应该去 IdPair 行查看与谁匹配【参考方案3】:表 2 实现了Entity-Attribute-Value 模型 (EAV),通常选择该模型是因为该模型相对于传统表模型(以及整个关系模型)具有一些优势。 EAV 的已知优势之一是基于多列值的 OR 搜索既高效又易于在传统模型中进行编码。
较新的 SQL 服务器实现提供的一些新功能也有助于 EAV 模型。
这就是说,总的来说,EAV 模型在逻辑模式方面带来的灵活性以及其他相关优势比其性能更有吸引力,尤其是在应用于数据库时具有超过一百万个实体(即,如果每个实体有许多属性,则可能有几千万个 EAV 条目)。 事实上,为了证明这一点,一些 EAV 实现引入了两种模型的混合,其中大多数实体共有的单值属性存储在“头文件”中,而不是存储在 EAV 列表中。
当然,关于这两个模型中哪一个更有效 [在 OR-ed 列值问题的限制性上下文中] 的最终决定取决于有效实现、索引和数据的统计概况。 对于较小的 EAV 表(例如这个有大约 500,000 个条目的表),EAV 模型在一般情况下可能会提供优势。
查看这篇相关的 SO 文章:database: EAV pros,cons and alternatives 一般扫描few SO articles with the eav tag。
【讨论】:
坦率地说,我在原始帖子中没有看到任何对 EAV 模型的引用。 @Remus,你是对的,唯一的参考是我自己添加的标签。但是,表 2 及其 ID、columnId 和 [奇怪的命名] IdPair 似乎是一个伪装得很薄的 EAV 实现(如果只是一个偶然的实现,如果 OP 没有明确知道这个模型)。 你仍然在整个 EAV 主题上发表了一篇不错的文章 :)【参考方案4】:很难说。我认为两者都应该具有相似的性能,或者可能第二个应该更好,因为 idColumn 是主键。检查查询执行计划并确保我有正确的索引。
【讨论】:
【参考方案5】:一个表比另一个更快的唯一原因是您在表上创建的索引。拥有第二个表没有性能优势,除非您没有在第一个表上创建正确的索引(或相反)。
例如,看起来第二个表更快,因为您在表 1 的 idcolumn1 和表 2 的 idcolumn 上创建了索引。如果您在表 1 的 idcolumn1 和 idcolumn2 上创建了另一个索引,那么您会看到非常相似的性能。
由于表 2 是重复数据,因此不建议维护此表。每次更新都需要更改两行。
但是,我看到此类数据的数据设计如下所示:
match table
-----------
matchid
additional match information
participants table
------------------
participantid
matchid
在此架构中,每个匹配项(以及任何附加数据)在匹配表中都有一行,并且您有一个类似于表 2 的表。它将参与者与匹配项关联起来。
然后你只需要对参与者进行选择并将其链接到匹配数据。
我相信这将是适合您情况的最佳做法。
【讨论】:
这些表只是一个例子。我的数据库中只有 Table2,我认为 Table2 是一种更好的存储方案是对的,因为它只需要创建 1 个索引即可获得所需的性能 我想了一会儿@pixel3cs 并想出了一个很好的设计......请参阅上面的编辑。 请澄清:instead you had made an index on idcolumn1 and idcolumn2 in table 1 then you would see very similar performance
不清楚您是要在表 1 的 和 列 2 上建议多列索引,还是要具有两个索引, 表 1 的每一列都有一个。组合索引肯定不会帮助 OP 指示的 OR 查询。
@mjv:当然组合索引没有帮助,我的意思是两个索引。我已经编辑了我的英语以使其更清晰。以上是关于SQL Server 2005:哪个更快?条件超过 2 列或超过 2 行?的主要内容,如果未能解决你的问题,请参考以下文章