我观察到,将数据插入内存优化表比在5-SSD条带集上基于磁盘的表的等效并行插入要慢得多。
--DDL for Memory-Optimized Table
CREATE TABLE [MYSCHEMA].[WIDE_MEMORY_TABLE]
(
[TX_ID] BIGINT NOT NULL
, [COLUMN_01] [NVARCHAR](10) NOT NULL
, [COLUMN_02] [NVARCHAR] (10) NOT NULL
--etc., about 100 columns
--at least one index is required for Memory-Optimized Tables
, INDEX IX_WIDE_MEMORY_TABLE_ENTITY_ID HASH (TX_ID) WITH (BUCKET_COUNT=10000000)
)
WITH (MEMORY_OPTIMIZED=ON, DURABILITY=SCHEMA_ONLY)
--DDL for Disk-Based Table
CREATE TABLE [MYSCHEMA].[WIDE_DISK_TABLE]
(
[TX_ID] BIGINT NOT NULL
, [COLUMN_01] [NVARCHAR](10) NOT NULL
, [COLUMN_02] [NVARCHAR] (10) NOT NULL
--etc., about 100 columns
--No indexes
) ON [PRIMARY]
对于这个特定的测试,我在这个表中以10,000个为一组批量处理10,000,000行。对于内存优化表,该语句看起来像这样:
--Insert to Memory-Optimized Table
INSERT INTO
WIDE_MEMORY_TABLE
(
TX_ID
, COLUMN_01
, COLUMN_02
--etc., about 100 columns
)
SELECT
S.COLUMN_01
, S.COLUMN_02
--etc., about 100 columns
FROM
[MYSCHEMA].[SOURCE_TABLE] AS S WITH(TABLOCK)
WHERE
S.TX_ID >= 1
AND S.TX_ID < 25001
OPTION (MAXDOP 4)
此过程继续加载10,000,000行。每次迭代只检索接下来的25,000行。 SELECT对[MY_SCHEMA]上的覆盖索引执行搜索。[SOURCE_TABLE]。查询计划向BIG_MEMORY_TABLE显示 序列化插入 。每组25,000行大约需要1400毫秒。
如果我对基于磁盘的表执行此操作,托管在5-SSD条带上(每个磁盘5,000 IOPS,吞吐量为200 MB /秒),插入进度要快得多,平均大约700毫秒。在基于磁盘的情况下,查询会对[MY_SCHEMA]执行 并行插入 。[WIDE_DISK_TABLE]。注意[MYSCHEMA]上的TABLOCK提示。[WIDE_DISK_TABLE]。
--Insert to Disk-Based Table
INSERT INTO
WIDE_DISK_TABLE WITH(TABLOCK)
(
TX_ID
, COLUMN_01
, COLUMN_02
--etc., about 100 columns
)
SELECT
S.COLUMN_01
, S.COLUMN_02
--etc., about 100 columns
FROM
[MYSCHEMA].[SOURCE_TABLE] AS S WITH(TABLOCK)
WHERE
S.TX_ID >= 1
AND S.TX_ID < 25001
OPTION (MAXDOP 4)
当然,基于磁盘的表没有索引,TABLOCK提示启用并行插入,但我希望从INSERT到RAM更多。
有什么想法吗?
谢谢!
以下是以3种模式运行的100个批次的比较:基于磁盘,创建延迟索引,基于磁盘的索引,以及使用索引进行内存优化(内存优化表上至少需要一个索引)。
答案 0 :(得分:5)
<强>更新强>
经过大量的测试和研究,我相信这归结为并行性。目前,SQL Server 2016(包括SP1 CU7)不支持并行插入内存优化表。 这使得内存优化表的所有INSERT语句都是单线程的。
以下是Niko Neugebauer关于此问题的精彩文章: Niko Neugebauer - Parallelism in Hekaton (In-Memory OLTP)
这使得它对ETL / ELT摄取的作用更小。但是,OLTP DML(特别是通过本机编译的存储过程)非常令人惊讶,而且在BI查询中聚合数据也很出色。对于摄取,只要你采取正确的步骤确保你的INSERT并行运行,几乎不可能在没有索引的情况下击败基于SSD的堆。
即使数据库处于完全恢复模式,并行INSERT到基于磁盘的堆也优于INSERT到内存优化表。如果在INSERT之后将可比较的索引添加到基于磁盘的表中,这仍将继续存在。