8

假设我的数据库中有一个包含1.000.000记录的表。

如果我执行:

SELECT * FROM [Table] LIMIT 1000

这个查询是否会花费与我有1000记录的表相同的时间,然后执行以下操作:

SELECT * FROM [Table]

?

我不是在寻找是否需要完全相同的时间。我只想知道第一个是否会比第二个花费更多的时间来执行。

我说1.000.000记录,但它可能是20.000.000。那只是一个例子。

编辑:
当然,当使用 LIMIT 并且不在同一个表中使用它时,使用 LIMIT 构建的查询应该执行得更快,但我不是在问...

为了使其通用:

Table1:X记录
Table2:Y记录

(X << Y)

我要比较的是:

SELECT * FROM Table1

SELECT * FROM Table2 LIMIT X

编辑2:
这就是我问这个的原因:

我有一个数据库,有 5 个表和其中一些表之间的关系。其中一张表将(我 100% 确定)包含大约5.000.000记录。我使用 SQL Server CE 3.5、Entity Framework 作为 ORM 和 LINQ to SQL 来进行查询。

我基本上需要执行三种非简单查询,并且我正在考虑向用户显示记录的限制(就像很多网站一样)。如果用户想查看更多记录,他/她可以选择限制更多的搜索。

所以,问题出现了,因为我正在考虑这样做(限制X每个查询的记录),或者如果只在数据库中存储X结果(最近的结果),这将需要在数据库中进行一些删除,但我只是在想...

因此,该表可能包含5.000.000记录或更多记录,而我不希望向用户显示1000左右,即使这样,查询仍然像返回5.000.000行一样慢。

4

3 回答 3

6

TAKE 1000从 1000000 条记录的表中 - 将快 1000000/1000 ( = 1000) 倍,因为它只需要查看(并返回)1000/1000000 条记录。既然做的少,自然就快了。

结果将是相当(伪)随机的,因为您没有指定任何要采取的顺序。但是,如果您确实引入了一个订单,那么以下两个之一将变为 true:

  1. ORDER BY 子句跟在索引后面——上面的语句仍然成立。
  2. ORDER BY 子句不能使用任何索引——它只会比不使用 TAKE 快一点,因为
    • 它必须检查所有记录,并按ORDER BY
    • 只交付一个子集(TAKE count)
    • 所以第一步并不快,但第二步涉及的 IO/网络比 ALL 记录少

如果您从 1000 条记录的表中 TAKE 1000 条记录,那么只要您遵循(1)无排序或(2)的情况,就相当于(几乎没有显着差异)从 10 亿条记录中提取根据索引排序

于 2011-04-19T04:41:17.833 回答
2

假设两个表在索引、行大小和其他结构方面是等效的。还假设您正在运行那个简单的 SELECT 语句。如果您的 SQL 语句中有ORDER BY子句,那么显然较大的表会更慢。我想你不是在问这个。

如果 X = Y,那么显然它们应该以相似的速度运行,因为对于这个简单的 SELECT 语句,查询引擎将以完全相同的顺序遍历记录——基本上是表扫描。查询计划不会有任何差异。

如果 Y > X 只是一点点,那么速度也差不多。

但是,如果 Y >> X(意味着 Y 的行数比 X 多得多),那么 LIMIT 版本可能会更慢。不是因为查询计划——同样应该是相同的——而仅仅是因为数据布局的内部结构可能有更多的层次。例如,如果数据以叶子的形式存储在树上,则可能会有更多的树级别,因此访问相同数量的页面可能需要稍微多一点的时间。

换句话说,例如,1000 行可以存储在 10 页中的 1 个树级别中。1000000 行可以存储在 10000 页中的 3-4 个树级别中。即使从这 10000 个页面中只取 10 个页面,存储引擎仍然需要经过 3-4 个树级别,这可能需要稍长一些的时间。

现在,如果存储引擎将数据页按顺序存储或以链表的形式存储,那么执行速度将没有差异。

于 2011-04-19T04:59:18.050 回答
1

只要您不指定任何字段、不指定排序和所有记录,它就会近似线性。但这并不能让你买太多。一旦您的查询想要做一些有用的事情,它就会崩溃。

如果您打算得出一些有用的结论并告诉我们在某些情况下使用它来做出设计选择的方式,这将更加有趣。

感谢您的澄清。

以我的经验,真实用户的真实应用程序很少有返回整百万行表的有趣或有用的查询。用户想了解他们自己的活动或特定的论坛主题等。因此,除非您的情况不寻常,否则当您真正掌握他们的选择标准时,您将谈论合理的结果大小。

无论如何,用户将无法对数百行以上的行做任何有用的事情,传输它们需要很长时间,并且他们无法以任何合理的方式滚动浏览它。

MySQL 具有 LIMIT 和 OFFSET (起始记录#)修饰符,主要是为了创建列表块以供您描述的分页。

It's way counterproductive to start thinking about schema design and record purging until you've used up this and a bunch of other strategies. In this case don't solve problems you don't have yet. Several-million-row tables are not big, practically speaking, as long as they are correctly indexed.

于 2011-04-19T05:05:17.570 回答