如何使用SQL Server CE表索引-是否值得为此查询执行此操作?
这是一个学习过程,我最终获得了一个运行SQL Server Compact Edition的查询 我最初的问题仍然存在,那就是如何提高性能。一些人评论说,我应该尝试为我的查询编制索引,以便这就是我现在看到的 此查询将获取一个学校中属于一个权重的所有玩家,并选择其中的最高技能,并将该玩家的起始值设置为true如何使用SQL Server CE表索引-是否值得为此查询执行此操作?,sql,indexing,sql-server-ce,Sql,Indexing,Sql Server Ce,这是一个学习过程,我最终获得了一个运行SQL Server Compact Edition的查询 我最初的问题仍然存在,那就是如何提高性能。一些人评论说,我应该尝试为我的查询编制索引,以便这就是我现在看到的 此查询将获取一个学校中属于一个权重的所有玩家,并选择其中的最高技能,并将该玩家的起始值设置为true cmd.CommandText = "UPDATE player " & "SET starter = 'TRUE' " &
cmd.CommandText = "UPDATE player " &
"SET starter = 'TRUE' " &
"WHERE NOT EXISTS" &
"(SELECT school, weight, skill " &
"FROM player b " &
"WHERE b.school = player.school " &
"AND b.weight = player.weight " &
"AND b.skill > player.skill)"
cmd.ExecuteNonQuery()
查询运行速度非常慢
- 我的“玩家”表约有170000名玩家
- 每个球员都属于4500所学校中的一所
- 每个运动员属于14个砝码中的一个
- 每所学校属于50个州中的一个
cmd.CommandText = "update p1 " &
"set starter = 'TRUE' " &
"from player as p1 " &
"left outer join player as p2 " &
"on p1.school = p2.school " &
"and p1.weight = p2.weight " &
"and p1.playerId <> p2.playerId " &
"and p1.skill <= p2.skill " &
"where(p2.playerId Is null)"
cmd.ExecuteNonQuery()
cmd.CommandText=“更新p1”&
“设置启动器='TRUE'”&
“从作为p1的播放器”&
“左外联球员作为p2”&
“关于p1.school=p2.school”&
“和p1.weight=p2.weight”&
“和p1.playerId p2.playerId”&
“p1.skill在这种情况下,运行sql所执行的代码有点让人困惑。我在下面重申了这一点:
UPDATE player SET starter = 'TRUE' WHERE NOT EXISTS
(
SELECT school, weight, skill
FROM player b
WHERE b.school = player.school
AND b.weight = player.weight
AND b.skill > player.skill
)
让我们首先看一下内部select语句。该语句本质上是从一个表“player”中请求一个包含三列(school、weight、skill)的结果表。您将该表别名为“b”。然后继续按三个方面进行筛选:b.school是否等同于player.school等等
第一个问题是,基于别名,b.school=player.school相当于player.school=player.school。对于前两个筛选器,将选择所有行-这是不必要的计算。但是,最终筛选器应始终返回false,这就是为什么查询很可能花费很长时间的原因:所有行都将是r从内部select语句返回
假设,在外部语句中,你将玩家别名为,比如,a,那么你将得到一个单独的结果,因为你现在问玩家a是否在同一个学校,是否有相同的体重,是否更好不过,在这种情况下,你要做的是将每个玩家与其他玩家进行比较:对于170000名玩家来说,这是170k^2或大约390亿次比较…这就是为什么这个查询如此缓慢的原因
有两种方法可以解决你的问题。第一种是通过编程来处理这些问题
选择所有唯一的学校作为查询
对于每个学校,运行类似的查询
另一个是做一个聪明的sql连接。这里我使用“playerId”作为一些列,它是唯一的标识符。(希望您的表有一个。)
通过使用内置的连接功能(3),此查询将运行得更快,并生成一个包含所有可能匹配的表(仅限同一学校和相同权重的玩家),然后根据技能进行筛选。原始结果表pre filter将比您使用的表小得多
最后一件事:使用“notexists”非常麻烦,可能会影响您的性能
UPDATE player c SET starter = 'TRUE' WHERE c.player IN
(
SELECT a.playerId
FROM player a INNER JOIN player b
ON ( a.school = b.school AND a.weight = b.weight)
WHERE a.skill > b.skill
)
(1) 注意:在某些sql实现中,内部语句中的“player”可能会被解释为外部语句中的“player”,但我不确定这是否可以保证。因此,您应该将其别名以确保
(2) 我不是100%的,因为我没有你的桌子可以玩
(3) SQL Server的构建通常是为了加快这方面的速度。但您必须知道如何使用它。在这种情况下,运行SQL所执行的代码有点让人困惑。我在下面重申了这一点:
UPDATE player SET starter = 'TRUE' WHERE NOT EXISTS
(
SELECT school, weight, skill
FROM player b
WHERE b.school = player.school
AND b.weight = player.weight
AND b.skill > player.skill
)
让我们首先看一下内部select语句。该语句本质上是从一个表“player”中请求一个包含三列(school、weight、skill)的结果表。您将该表别名为“b”。然后继续按三个方面进行筛选:b.school是否等同于player.school等等
第一个问题是,基于别名,b.school=player.school相当于player.school=player.school。对于前两个筛选器,将选择所有行-这是不必要的计算。但是,最终筛选器应始终返回false,这就是为什么查询很可能花费很长时间的原因:所有行都将是r从内部select语句返回
假设,在外部语句中,你将玩家别名为,比如,a,那么你将得到一个单独的结果,因为你现在问玩家a是否在同一个学校,是否有相同的体重,是否更好不过,在这种情况下,你要做的是将每个玩家与其他玩家进行比较:对于170000名玩家来说,这是170k^2或大约390亿次比较…这就是为什么这个查询如此缓慢的原因
有两种方法可以解决你的问题。第一种是通过编程来处理这些问题
选择所有唯一的学校作为查询
对于每个学校,运行类似的查询
另一个是做一个聪明的sql连接。这里我使用“playerId”作为一些列,它是唯一的标识符。(希望您的表有一个。)
通过使用内置的连接功能(3),此查询将运行得更快,并生成一个包含所有可能匹配的表(仅限同一学校和相同权重的玩家),然后根据技能进行筛选。原始结果表pre filter将比您使用的表小得多
最后一件事:使用“不存在”是非常困难的,可能会影响您的性能。试试看
WHERE b.RowId = player.RowId
update p1
set starter = 'TRUE'
from player as p1
left outer join player as p2
on p1.school = p2.school
and p1.weight = p2.weight
and p1.playerId <> p2.playerId
and p1.skill <= p2.skill
where p2.playerId is null
create index player_i01 on player ( school, weight, skill, playerId )