【问题标题】:What is the Fastest Way to Select a Whole Table in SQL Server?在 SQL Server 中选择整个表的最快方法是什么?
【发布时间】:2011-03-10 13:18:22
【问题描述】:

我正在编写一个应用程序,它读取整个表,进行一些处理,然后将结果数据写入另一个表。我正在使用SqlBulkCopy 类(“bcp in”的.net 版本),它的插入速度非常快。但是我首先找不到任何有效的方法来选择数据。没有 .net 等价于“bcp out”,这对我来说似乎很奇怪。

目前我正在使用select * from table_name。例如,选择 6,000 行需要 2.5 秒……而批量插入相同数量的行只需 600 毫秒。

我希望选择数据应该总是比插入更快。 从表中选择所有行和列的最快方法是什么?


问题解答:

  • 我将选择时间设置为 2.5 秒 2 种方式。首先是在运行我的应用程序并运行 sql 跟踪时。第二个是在 SSMS 中运行相同的查询。两者都返回了大致相同的结果。
  • 我正在使用 SqlDataReader 读取数据。
  • 没有其他应用程序正在使用此数据库。
  • 我目前的处理时间不到 1 秒,所以 2+ 秒的读取时间比较长。但在将其扩展到 100,000 行和数百万行时,我最关心(感兴趣)性能。
  • Sql Server 08r2 和我的应用程序都在我的开发机器上运行。
  • 一些数据处理是基于设置的,所以我需要将整个表放在内存中(为了支持更大的数据集,我知道这一步可能需要移到 SQL 中,所以我只需要在记忆)

这是我的代码:

DataTable staging = new DataTable();
using (SqlConnection dwConn = (SqlConnection)SqlConnectionManager.Instance.GetDefaultConnection())
{
    dwConn.Open();
    SqlCommand cmd = dwConn.CreateCommand();
    cmd.CommandText = "select * from staging_table";

    SqlDataReader reader = cmd.ExecuteReader();
    staging.Load(reader);
}

【问题讨论】:

  • 您的处理需要多长时间?
  • 你是如何测量这 2.5 秒的?在 SSMS 中还是在您的应用程序中?如果是前者,如果您打开选项“执行后丢弃结果”以消除 SSMS 处理时间。如果是后者,您的应用程序如何检索行 - 例如,您是否使用数据阅读器?你的代码是什么样的?
  • 当您从该表读取数据时,是否有其他应用程序写入该表?如果是这样,您可能想尝试使用“WITH (NOLOCK)”选项。
  • 不一定。读取时您必须在磁盘上找到数据,但写入时您只是写出到指定的位置。您可以尝试创建一个新索引,并定期重建/重组,以提高读取效率。
  • 我认为您需要提供一些有关您如何计时的详细信息。您使用的是 DataAdapter 还是 DataReader?你是如何管理你的连接的?可能还有其他一些问题。如果您可以发布您的计时代码,那将很有帮助。

标签: c# .net sql sql-server-2008


【解决方案1】:

select * from table_name 读取整个表格的最简单、最简单、最快的方法。

让我解释一下为什么你的结果会导致错误的结论。

  1. 复制整个表是一种优化操作,只需克隆旧的二进制数据到新的二进制数据中(根据存储机制,最多可以执行文件复制操作)。
  2. 写入被缓冲。 DBMS 表示记录已写入,但实际上尚未完成,除非您处理事务。磁盘操作通常会延迟。
  3. 查询表还需要(与克隆不同)将数据从二进制存储的布局/格式调整为最终可由客户端读取的依赖于驱动程序的格式。这需要时间。

【讨论】:

    【解决方案2】:

    这完全取决于您的硬件,但您的网络很可能是这里的瓶颈。

    除了将您的查询限制为仅读取您实际使用的列之外,执行选择的速度也很快。这里涉及到缓存,当你连续执行两次时,第二次应该会快得多,因为数据缓存在内存中。执行dbcc dropcleanbuffers查看缓存效果。

    如果您想尽快完成,请尝试实现在 T-SQL 中执行处理的代码,这样它就可以直接对服务器上的数据进行操作。

    另一个速度调整的好技巧是在一个磁盘上读取表(查看文件组)和在另一个磁盘上写入的表。这样,一个磁盘可以进行连续读取,而另一个磁盘可以进行连续写入。如果这两种操作都发生在同一个磁盘上,那么磁盘的磁头会不断来回移动,这会严重降低性能。

    如果你写的逻辑不能用 T-SQL 写,你也可以看看 SQL CLR。

    另一个提示:当您从表中选择 * 时,请尽可能使用数据阅读器。这样你就不会首先在内存中实现整个事情。

    GJ

    【讨论】:

      【解决方案3】:

      在选择列表中包含列名通常是一个好主意,但是对于今天的 RDBMS,它不会有太大的区别。如果您限制选定的列,您只会看到这方面的差异。一般来说,包含列名是一种很好的做法。但是要回答,似乎选择确实比在您描述的场景中插入要慢 是的,select * from table_name 确实是从表中读取所有行和列的最快方法

      【讨论】:

      • +1,因为这 IS 很有帮助,并且包含了一个我同意的好点,这不在其他答案中。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-09-24
      • 1970-01-01
      • 2020-01-09
      • 1970-01-01
      • 2011-02-21
      • 1970-01-01
      • 2019-10-28
      相关资源
      最近更新 更多