如何提高SQL Server的读取速度?

时间:2019-05-09 22:36:38

标签: sql sql-server ssis

我正在尝试将表从一个SQL Server复制到另一个。源是SQL Server 2014,目标是SQL Server2016。我无法获得高于60MB / s的速度。我要复制约15亿行,总表大小约为1TB。

源服务器具有RAID 5的SATA SSD,目标服务器具有RAID 0的NVME SSD。两台机器都通过10GbE直接连接,没有任何交换机。我能够在几秒钟内复制几GB的文件,所以我认为网络和磁盘都已正确配置。

我正在使用SSIS,并且我只尝试了一个“表”源和一个select *查询。程序包将创建目标表,而我正在使用快速加载。我已经尝试过将oledb用于SQL Server,并将SQL本机客户端用于连接类型。我在数据流中尝试了1到12个并行源/目的地的任何地方,但速度却是从1到12的3倍。但是我没有简单的方法来进一步划分数据以提高并行度。 >

我玩了缓冲区,并且数据包大小无济于事。

源表大约有100列。

我希望为此至少获得300-500MB / s的速度,并希望至少使源磁盘的读取速度达到饱和(〜800MB / s)。我是否缺少某些东西,或者这仅仅是SQL Server的局限性?

3 个答案:

答案 0 :(得分:1)

对于这个问题,我没有具体的答案,但是我会尝试提供一些可能会提供一些见解的信息:

选择特定列

首先,如果在OLE DB源中不使用某些列,请更改Access Mode并使用SQL Command而不是Table or View并在Select中指定所需的列查询。例如,如果表包含5列[Col1],[Col2], ... [Col5],而您只需要[Col1],[Col2],则使用以下查询:

Select [Col1],[Col2] From [Table]

代替选择Table name

有关更多信息:

最小化日志记录

您可以尝试使用一种方法,该方法是通过使用聚集索引来最大程度地减少日志记录。请查看下面的链接以获取更多信息:

平衡数据分配器

您还可以从Balanced Data Distribution Transformation中受益,以增强数据加载性能:

有用的文章

2008年,Microsoft发布了一份白皮书,宣布使用Microsoft SQL Server集成服务(SSIS)打破记录的数据负载:在不到30分钟的时间内达到1 TB的数据。它可能会给您一些见识:

我认为有很多方法可以提高INSERT查询的性能,建议阅读以下文章以获取有关数据加载性能的更多信息。


还要检查有关Max Insert Commit Size属性,数据类型,批量插入...的@billinkc注释...

答案 1 :(得分:0)

好久没问这个问题了。
感谢所有做出贡献的人。

我尝试了所有建议,但结果喜忧参半。我不想进入输出文本文件然后重新导入它们的过程,我需要保留表中的所有列。

最后让我“尽可能快”的唯一事情是创建没有索引的目标表,运行 32 个并行读/写数据流,然后创建必要的索引。

我永远无法使 10Gb 连接饱和,但目标计算机 (Threadripper 2950X) 上 CPU 的所有 32 个线程都已达到 100%。这可能是由于软件 NVME RAID。

使用这种方法并调整插入提交大小最终让我达到了大约 600-700MB/s。之后添加聚集索引相当快,只需几分钟。

希望这对尝试做同样事情的其他人有所帮助。

答案 2 :(得分:0)

除了 OleDB 和 Native Client,您是否尝试过编写存储过程,以便 SQL 直接在设备之间的引擎中执行此操作。我们不知道您的实际流程是什么,也不知道您创建的决赛桌是如何准备的。您的“包”创建过程涉及哪些过程。您提到了一个示例“从 SomeTable 中选择 *”,但没有获得任何性能。

如果您有 10 到 12 个进程试图读取和写入正在创建的同一个表,那么可以这么说,您是不是在割自己的喉咙?此外,目标表上有多少索引。删除所有索引可能对性能有益,但可能只有主键 ID 除外。如果您在表上使用 CLUSTERED 索引,那么它会在写入时不断对数据进行排序(据我所知)。此外,您将处理冲突,必须等待一个进程完成插入,而下一个进程有机会继续执行。

如果你做了类似的事情

select 
      YT.*
   into
      YourNewDatabase.dbo.YourNewTable
   from
      YourPrimaryDatabase.dbo.YourMainTable

SQL 引擎将有一个单一的活动流读取所有原始数据页,如果聚集将在没有显式聚集索引的情况下写出在新驱动器上的同一个已经预先排序的聚集中。您也没有任何东西返回到您的本地机器以供“包”处理。一旦数据完全在另一个驱动器上,那么您可以一次构建所有索引,而不是一个接一个地单独创建。

我不知道 SQL-Server 与 MySQL 如何在幕后“创建索引”,但很多年前,我正在研究数据挖掘系统。该流程的表包含 21 多万条记录,并且系统有大约 20 个基于查询可用情况的索引。如果我一次创建一个索引,然后一个,然后另一个,就像它增加了时间。第一个索引 = 20 分钟。第二个索引 = 40 分钟,第三个 = 1 小时,等等。但是如果我为 1、2 和 3 创建一个索引,整个索引创建大约需要 35 分钟。必须是索引和页面的写入方式。因此,您可能也需要考虑一下。

因此,对于从设备 A 到 B 的直接复制,我会尝试这样做。使用/不使用索引,试试看。如果您是从 SQL1 中拉出数据在本地进行处理,然后再推回 SQL2 以获取 BILLION+ 条记录,这显然需要时间。