0

SELECT One, Two, Three 与 SELECT One, Two, Three, ..... N-Column 相比的成本有多大

如果您有一个将两个或三个表连接在一起并检索 100 行数据的 sql 查询,那么性能是否说明我是否应该只选择我需要的列数?或者我应该写一个查询,只是拉出所有的列..

如果可能的话,您能否帮助我了解查询的哪些方面相对而言成本相对较高?是联接吗?是拉的大量记录吗?是选择语句中的列数吗?

1 条记录 vs 10 条记录 vs 100 条记录重要吗?

4

10 回答 10

2

作为对您在编写的查询中的性能损失和出现率方面提到的那些因素进行排名的一个非常通用的版本,我想说:

  1. 连接- 特别是在连接没有您要连接的字段的索引的表和/或具有大量数据的表时。
  2. # of Rows / Amount of Data - 同样,索引减轻了这一点,只要确保你有正确的。
  3. # of Fields - 我会说 SELECT 子句中的 # of fields 在大多数情况下对性能的影响最小。

我会说任何驱动性能的属性总是与您拥有多少数据相结合 - 当您的表每个有 100 行时,连接可能会很快,但是当表中有数百万行时,您必须开始考虑更高效设计。

于 2010-11-17T17:16:58.567 回答
2

有几件事会影响查询的成本。

首先,是否有合适的索引供它使用。连接中使用的字段几乎总是应该被索引并且默认情况下外键不被索引,数据库的设计者必须创建它们。where 子句中使用的字段通常也需要索引。

接下来,where 子句是否可搜索,换句话说,即使您有正确的索引,它也可以使用索引吗?一个糟糕的 where 子句对查询的伤害远远超过连接或额外的列。如果您使用阻止使用索引的语法,则只能进行表扫描,例如:

LIKE '%test'

接下来,您返回的数据是否超出了您的需要?您永远不应该返回比您需要的更多的列,并且您不应该在生产代码中使用 select *,因为它需要额外的工作来查找列,并且非常脆弱并且随着结构随时间的变化而产生错误的错误。

您是否要加入不需要加入的表?如果一个表在 select 中没有返回任何列,没有在 where 中使用,并且如果连接被删除,也不会过滤掉任何记录,那么你有一个不必要的连接,它可以被消除。当您使用大量视图时,不必要的连接尤其普遍,尤其是当您错误地从其他视图调用视图时(由于可能的原因,这是一个错误的性能杀手)有时如果您跟踪调用其他视图的这些视图,您将如果查询是从头开始而不是使用视图编写的,则不需要多次连接同一个表。

返回的数据多于您需要的数据不仅会导致 SQL Server 更加努力地工作,而且如果您将结果保存在内存中,它还会导致查询使用更多的网络资源和 Web 服务器的更多内存。这是一个全方位的糟糕选择。

最后,当有更好的技术可用时,您是否使用已知的性能不佳的技术。这将包括在基于集合的替代方案更好时使用游标,在连接更好时使用相关子查询,使用标量用户定义函数,使用调用其他视图的视图(特别是如果您嵌套不止一个级别。大多数这些糟糕的技术都涉及逐行处理,这通常是数据库中最糟糕的选择。要正确查询数据库,您需要考虑数据集,而不是一次处理一行.

还有很多事情会影响查询和数据库的性能,要真正掌握这个主题,你需要阅读一些关于这个主题的书籍。这是一个太复杂的主题,无法在留言板中充分讨论。

于 2010-11-17T19:21:33.150 回答
1

或者我应该写一个查询,只是拉出所有的列..

不,就在今天,还有一个关于这个的问题

如果可能的话,您能否帮助我了解查询的哪些方面相对而言成本相对较高?是联接吗?是拉的大量记录吗?是选择语句中的列数吗?

任何无用的连接或数据检索都会耗费您的时间,应该避免。从数据存储中检索行的成本很高。连接的成本或多或少取决于上下文、定义的索引数量……您可以检查每个查询的查询计划以查看每个步骤的估计成本。

于 2010-11-17T17:09:25.717 回答
1

选择更多的列/行会对性能产生一些影响,但老实说,你为什么要选择比你将要使用的更多的数据呢?

如果可能的话,您能否帮助我了解查询的哪些方面相对而言成本相对较高?

构建您需要的查询,然后在性能不符合您的期望时担心对其进行优化。你是把马放在车前。

于 2010-11-17T17:09:35.493 回答
0

简短回答:不要选择比您需要的更多字段 - 在源代码和存储过程中搜索“*”;)

您总是必须考虑查询的哪些部分会导致哪些成本。

如果你有一个好的数据库设计,加入几个表通常并不昂贵。(确保您有正确的索引)。

“select *”的主要问题是它会导致结果中出现不可预测的行为。如果您编写这样的查询,并使用 columnindex 访问字段,您将永远被锁定在 DB-Schema 中。

要考虑的另一件事是您必须考虑的数据量。您可能认为它微不足道,但您的应用程序的 Version2.0 突然将 ProfilePicture 添加到 User 表中。而现在将选择 100 个用户的查询将突然占用几兆字节的带宽。

您应该考虑的第二件事是您返回的行数。SQL在排序和分组方面非常强大,所以让SQL完成他的工作,不要把它移到客户端。限制您返回的记录数量。在大多数应用程序中,一次向用户返回超过 100 行是没有意义的。你可以让用户选择加载更多,但让它成为他必须做出的选择。

最后,监控您的 SQL Server。对它运行分析器,并尝试找到最糟糕的查询。SQL Query 不应该花费超过半秒的时间,如果是这样,则很可能会出现问题(是的......有些操作可能需要更长的时间,但那些应该有原因)

编辑:一旦你发现慢查询,看看执行计划......你会看到查询的哪些部分是昂贵的,哪些部分运行良好......优化器也是一个可以使用的工具。

于 2010-11-17T19:34:05.637 回答
0

SELECT One, Two, Three FROM ...和之间的区别SELECT One,...,N FROM ...可能就像白天和黑夜之间的区别。要理解这个问题,您需要了解覆盖索引的概念:

覆盖索引是一种特殊情况,索引本身包含所需的数据字段并可以返回数据。

当您向投影列表添加更多不必要的列时,您会强制查询优化器在“表”中查找新添加的列(实际上是在聚集索引或堆中)。这可以将执行计划从有效的窄索引范围扫描更改或查找到臃肿的聚集索引扫描,这可能导致时间差异从亚秒到 + 小时,具体取决于您的数据。因此,投影不必要的列通常是查询中影响最大的因素。

提取的记录数量是一个更微妙的问题。如果数量很大,查询可以达到索引临界点并再次选择聚集索引扫描,而不是更窄的索引范围扫描和查找。现在,必须首先查找聚集索引的事实意味着窄索引没有覆盖,这最终可能是由于投影了不必要的列。

最后,加入。这里的问题是加入,而不是什么?如果需要加入,则别无选择,这就是要说的全部内容。

最终,查询性能仅由一个因素驱动:IO 量。IO 的数量最终由可用于满足查询的访问路径驱动。换句话说,通过您的数据的索引。对坏索引编写有效的查询是不可能的。可以在良好的索引上编写错误的查询,但优化器通常可以弥补并提出一个好的计划。您应该全力以赴更好地理解索引设计:

于 2010-11-17T18:15:17.090 回答
0

要回答以下问题:

SELECT One, Two, Three 与 SELECT One, Two, Three, ..... N-Column 相比的成本有多大

这不是选择性能的问题,而是获取数据所需的时间。 Select * from TableSelect ID from Table执行相同的操作,但获取数据需要更长的时间。这与查询返回的行数密切相关。

至于在这里理解性能是一个很好的链接

http://www.dotnetheaven.com/UploadFile/skrishnasamy/SQLPerformanceTunning03112005044423AM/SQLPerformanceTunning.aspx

或谷歌 tsql 性能

于 2010-11-17T17:09:35.227 回答
0

连接可能会很昂贵。在最坏的情况下,当没有索引可以使用时,它们需要 O(M*N) 时间,其中 M 和 N 是表中的记录数。为了加快速度,您可以CREATE INDEX在属于连接条件的列上。

列数对查找行所需的时间影响不大,但会因需要发送更多数据而减慢速度。

于 2010-11-17T17:22:33.097 回答
0

别人说的都是真的。

但通常情况下,如果您正在使用已经具有良好索引的表,那么对性能最重要的是 WHERE 语句中的内容。在那里,您必须更多地担心使用没有索引的字段或使用无法优化的语句。

于 2010-11-17T17:29:22.153 回答
0

我建议您首先考虑 I/O 方面的查询。我的 SATA II 系统上的磁盘 I/O 为 6Gb/秒。我的 DDR3 内存带宽是 12GB/秒。我在内存中移动项目的速度比从磁盘中检索的速度快 16 倍。(参考维基百科和汤姆的硬件)

为 100 行获取几列和所有列之间的区别可能是从磁盘获取单个 8K 页面与从磁盘获取两个或更多页面的差异。当页面最终在内存中时,将两列或所有列移动到哈希表比我拥有的任何测量工具都要快。

我重视其他人在这个与数据库设计相关的主题上的建议。窄索引的设计,使用包含的列来制作覆盖索引,通过使用适当的 WHERE 子句,窄主键等来避免表或索引扫描,这是拥有 DBA 头衔和成为 DBA 之间的区别。

于 2010-11-18T02:11:46.927 回答