0

我有一个基本的 sql 选择问题,多年来人们给了我不同的答案。假设我有几个表,每个表都设计有超过 40 列,并且可能会容纳十万行,我使用的是 SqlServer2005。

在加入这些表时,在 where 子句中,如果我有类似的东西

select * from t1, t2
where t1.UserID = 5 
and t1.SomeID = t2.SomeOtherID

有人说你应该总是在前面设置常量“t1.UserID = 5”而不是在“t1.SomeID = t2.SomeOtherID”之后,这样可以提高选择性能。虽然其他人说没关系。

正确答案是什么?

另外,如果我使用 ADO.NET Entity Framework 来实现我的 DAL,那么对具有 40 多个列的表进行建模并执行 CRUD 操作是否会成为性能问题?

谢谢,

射线。

4

4 回答 4

4

一般来说,对于数据库优化,您应该首先编写概念上正确的 SQL,然后在分析表明有必要时调整性能。在进行内部联接时,最好使用 SQL-92,显式 INNER JOIN,而不是笛卡尔积。因此,我将从编写您的 SQL 开始,如下所示:

SELECT * 
FROM t1
  INNER JOIN t2
    ON t1.SomeID = t2.SomeOtherID
WHERE
  t1.UserID = 5 

INNER JOIN 的 ON 部分中的 t1.SomeID = t2.SomeOtherID,因为它表达了两个表之间的关系。进入 WHERE 子句的用户 ID,因为它是限制结果集的过滤器。以这种方式编写 SQL 可为数据库优化器提供更多信息,因为它表达了您对连接与过滤的意图。

现在,如果您在真实世界的数据库中使用此语法无法获得可接受的性能,那么请随意尝试移动位。但就像我说的,从概念上正确的东西开始。

关于您问题的第二部分,最明显的性能暗示是,当您选择实体集合时,实体框架需要恢复它正在实现的实体的所有属性。因此,如果您有 40 列,那么您将通过网络将这些数据拉回,如果您将它们具体化为实体。但是,可以编写返回只包含您需要的列的匿名类型的 LINQ 查询。但是,要执行完整的 CRUD,您将需要返回实体。

于 2008-12-17T22:46:00.100 回答
2

人们对此的看法会随着时间而改变,因为 RDBMS 查询优化随着时间的推移而发展,不同的 RDBMS 会有不同的方法。我不能代表所有系统,但在 2008 年这真的不太可能产生任何影响。如果您只对特定系统感兴趣,请使用 YMMV。

我可以告诉你,对于任何最新版本的 Oracle,它都没有区别。

于 2008-12-18T17:30:49.223 回答
1

我知道这个答案有点陈词滥调,但我建议编写基准。开发一个控制台应用程序并自己进行测试。运行查询几百次,看看每种方式需要多长时间。

关于 SQL 查询性能和优化,有很多迷信。有些人做事认为它更快,但他们实际上并没有检查他们的事实。此外,EF 或 LinqToSql 工作和与数据库交互的方式可能会引入 SQL 中不明显的性能差异。

如果您正在优化代码,您可能还想使用像 RedGate ANTS 这样的分析器。它不是免费的,但它可以帮助您找到代码中的瓶颈。然后你可以在你的代码中找到更容易优化的地方。降低应用程序速度的并不总是您的数据库。或者有时你正在执行一个快速查询,但是当你实际上可以缓存结果时却做了很多次。

于 2008-12-17T22:47:53.747 回答
0

Firstly, construct the query using an explicit JOIN syntax, rather than the cartesian product. It probably won't make any difference performance-wise for any modern optimiser, but it does make the information on how the JOINs work more accessible for the programmers.


SELECT Player.Name, Game.Date
 FROM Player
  INNER JOIN Game ON Game.WinnerPlayerID = Player.PlayerID
 WHERE Game.WinnerFrags > Game.TotalFrags/2
 ORDER BY Player.Name

Which will give us all the players sorted by name who have take more frags in a game than all the other players in the game put together, and the dates of the games. Putting both the conditions are in the JOIN probably won't affect performance either, since the optimiser is likely do the filtering as part of the JOIN anyway. It does start to matter for LEFT JOINs though. Lets say we're looking for how many games the week's top ten players have ever won by the margin described above. Since it is possible that some of them have never one this spectacularly, we'll need LEFT JOIN.


SELECT Player.WeekRank, Player.Name, COUNT(Game.*) AS WhitewashCount
 FROM Player
  LEFT JOIN Game ON Game.WinnerPlayerID = Player.PlayerID
 WHERE Player.WeekRank >= 10
  AND Game.WinnerFrags > Game.TotalFrags/2
 GROUP BY Player.WeekRank, Player.Name
 ORDER BY Player.WeekRank

Well, not quite. The JOIN will return records for each game played by a player, or the player data and NULL game data if the player has played no games. These results will get filtered, during or after the JOIN depending on the optimiser's decision, based on the frag criteria. This will eliminate all the records that don't meet the frag criteria. So there will be no records to group for players who have never had such a spectacular win. Effectively creating an INNER JOIN .... FAIL.


SELECT Player.WeekRank, Player.Name, COUNT(Game.*) AS WhitewashCount
 FROM Player
  LEFT JOIN Game ON Game.WinnerPlayerID = Player.PlayerID
   AND Game.WinnerFrags > Game.TotalFrags/2
 WHERE Player.WeekRank >= 10
 GROUP BY Player.WeekRank, Player.Name
 ORDER BY Player.WeekRank

Once we move the frag criteria into the JOIN the query will behave correctly, returning records for all players in the week's top ten, irrespective of whether they've achieved a whitewash.

After all of that, the short answer is:

For INNER JOIN situations it probably doesn't make a to performance difference where you put the conditions. The queries are more readable if you separate the the join and filtering conditions though. And getting a condition in the wrong place can seriously mess up the results of a LEFT JOIN.

于 2008-12-29T15:25:58.713 回答