SQL BULK插入/ BCP导出后未释放使用的内存


10

我创建了一个非常基本的SQL表,如下所示

CREATE TABLE [dbo].[TickData](
[Date] [varchar](12) NULL,
[Time] [varchar](12) NOT NULL,
[Symbol] [varchar](12) NOT NULL,
[Side] [varchar](2) NOT NULL,
[Depth] [varchar](2) NOT NULL,
[Quote] [varchar](12) NOT NULL,
[Size] [varchar](18) NOT NULL
    ) ON [PRIMARY]

然后,我执行了3 Gig批量插入

    BULK
    INSERT TickData
    FROM 
    'C:\SUMO.csv'
    GO

然后SQL Server的RAM使用量激增,吞噬了约30Go的RAM:

在此处输入图片说明

在此处输入图片说明

我更倾向于认为这是一种异常行为,可以采取措施避免这种情况。

编辑:
好的,这似乎是默认行为。很公平。
但是,为什么在大容量插入完成后很长时间没有释放内存

几个额外的考虑因素:
关于SQL Server被操作系统“告知”时释放内存的评论,我在24核32 Gb Xeon Server上的动手经验证明这是不精确的:一旦内存占用过多的BCP提取结束了我的数据处理应用程序中有一个.Net实例池,需要处理提取的数据,它们被阻塞/争斗以共享剩余内存以尝试执行其工作,这比打开SQL Server时花费的时间更长关闭,内存可供所有应用程序共享。我必须停止SQL Server代理,以使一切顺利进行,并防止因Articiallt导致OutOfMemmroy异常而使应用程序崩溃。对于人为的残酷内存封顶/限制,如果有可用内存,为什么不使用它?理想情况下,宁愿将其设置为适应可用的内容,而不仅仅是“随机”限制。但是我想这是设计使然,因此在最后一点上案例不公开。


6
为什么SQL Server应该释放内存?如果需要内存一次执行此操作,则将再次需要它。如果SQL Server释放了内存,您将如何使用它?为什么需要释放内存?如果您将内存用于其他用途,则此批量插入将再次运行,应该怎么办?
亚伦·伯特兰

您唯一可以避免的操作就是设置最大内存大小。若要“恢复”内存,可以重新启动SQL Server服务。显然,这将释放内存,并且当服务重新启动时,它将正常分配内存。
TMN 2012年

我清理了最后的编辑。如果您想就如何编码SQL Server(或任何其他DB引擎)的优缺点进行争论/讨论,请找一个更好的地方。原来的问题已被回答,显然正确且充分。如果此Q持续蠕变,可能会被锁定。
JNK 2012年

想要知道答案并讨论方法并没有错,只是不在问答网站上。您绝对可以在聊天室或某个论坛中进行此讨论,但是Stack Exchange的结构更为合理,讨论很快的问题将被关闭。
JNK 2012年

3
另外,作为非主持人,我想知道为什么您在服务器上运行非SQL东西?该框应保留为仅供SQL Server使用,就像DBA 101一样。该引擎不是为共享资源环境设计的。
JNK

Answers:


12

对于SQL Server,正常的行为是在其缓冲池中分配尽可能多的内存。数据库在有大量缓冲区的情况下效果最佳。如果要更改行为,可以设置“最大服务器内存”设置。这里有一些很好的背景阅读


1
关于您的编辑,Aaron的评论很好。原因是数据库服务器释放内存的意义不大。如果确实需要,SQL Server会响应内存压力并释放内存,但这实际上不是必须的。
马特·惠特菲尔德

@MikaJacobi抱歉,您的第二次编辑是错误的。从开发人员的角度来看,我理解您的观点,但是在构建一堆共存的应用程序和服务器服务(实际上应该是计算机上唯一消耗内存的服务)之间存在差异。如果您希望SQL Server表现得像“普通”应用程序,则设置最大内存并走开。您的问题是为什么它会以这种方式工作,并且已经得到答复。如果您现在的问题是“恩,我不喜欢这样工作” –对不起,但这不再是一个问题。
亚伦·伯特兰

很公平。我的观点是,应该选择启用或禁用此选项,并且假设SQL Server是服务器上唯一的应用程序确实是滥用的(对于拥有大型网络的大公司可能是正确的,但这不是唯一的选择)可能也不是最常见的设置)
Mehdi LAMRANI 2012年

我仍然不明白为什么您需要SQL Server释放内存。如果其他应用程序需要它,他们将从SQL Server取回它,并且SQL Server将遵从。在其他应用程序需要它之前,释放内存的作用是什么?
亚伦·伯特兰

1
@AaronBertrand好吧,我可能是错的,但是正如我在上一次新编辑中所述,这不是我亲眼所见:当其他应用程序几乎不需要它时,内存没有被释放,导致内存崩溃(因此,我不满意...)无论如何,让我们结束话题,我想没有必要再多争论了。
Mehdi LAMRANI 2012年

7

如果您确实希望操作系统从SQL Server夺回内存,请提取20 GB的大文件并通过网络复制它。SQL Server将根据操作系统需要释放内存。但是在进行此操作时,我将观察各种性能计数器,并查看在复制进行中或复制后立即再次运行BULK INSERT的性能如何变化。

如果要手动执行此操作,则应为SQL Server的最大服务器内存设置设置一个下限,然后重新启动服务。现在,即使需要,SQL Server也不会使用28GB。但这似乎是人为限制SQL Server。

您似乎期望的是更灵活的行为,即您可以在部分时间拥有空闲内存。出于什么目的?这是否就像收缩数据库文件以释放磁盘空间(由于该数据库文件将再次增长)而无法将其用于其他目的一样?

有趣的是,如果您在Google搜索中键入“为什么不使用SQL Server”,最常见的自动完成功能是“释放内存”。



“您似乎期望的是更灵活的行为。” 究竟。我希望SQL Server在可用时使用所有可用的内存,但是当这些繁重的时刻结束后,请返回“睡眠”状态并让其他需要内存的应用程序轻松地完成其工作(您可以查看一下关于这一点的最新修改)
Mehdi LAMRANI

有关说明为什么我需要这样做的具体案例,您可以在问题的底部@ @我对JNK的最后评论
Mehdi LAMRANI 2012年

4

不幸的是,这是设计使然,请参考此帖子。但是,本文确实为您提供了有关如何控制它的说明。

/server/251832/sql-server-bulk-insert-physical-memory-issue

内存分配

内存没有freed用完,因为它像.NET应用程序一样分配内存。由于内存分配很昂贵,除非操作系统要求,否则它将坚持该分配。但是,不必担心,如果操作系统需要内存,它将获得它,就像在.NET应用程序中一样。


@MikaJacobi当然,没问题。需要注意的另一件事是,SQL Server也将接管所有内核,因此请确保限制可用内核的数量。我已经看到SQL Server实际上破坏了以前运行的操作系统,并且我不得不硬重启数据中心SQL Server。

很高兴知道。我有24核,所以现在还可以。但是,为什么大容量插入结束后没有释放内存?

只要大容量插入完成,如果操作系统需要内存,它将被分配给它,但是它分配内存的方式与.NET应用程序非常相似,因此,如果需要它,没有其他人可以更快地访问它。

我的乏味经验与此矛盾(最后一次编辑)。
Mehdi LAMRANI
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.