TRUNCATE TABLE [ReadDB].[dbo].[Price] GO INSERT INTO [ReadDB].[dbo].[Price] SELECT a.*,0 as ValueUSD,0 as ValueEUR from [WriteDB].[dbo].[Price] a JOIN [ReadDB].[dbo].[Companies] b ON a.QuoteId = b.QuoteID
所以最初大约有130万.此表中的行(~50GB).每天他们中的一些人都会添加,其中一些会发生变化,所以现在我们决定不复杂逻辑,只重新导入所有数据.由于某种原因,由于某些原因,这个脚本的工作时间越来越长,几乎相同的数据量.首先运行它需要〜1小时,现在它已经花了3小时
另外sql Server导入后工作也不顺利.导入(或在其中)如果我尝试运行不同的查询,即使是最简单的,它们通常也会因超时错误而失败.
这种不良行为的原因是什么以及如何解决这个问题?
解决方法
考虑以下事件序列:
>您将初始数据集加载到WriteDb中.在加载操作期间,WriteDb中的页面被缓存.内存争用非常少,因为只有一个数据集副本和足够的内存.
>您最初填充ReadDb.填充ReadDb所需的页面(WriteDb中的数据)已经在很大程度上被缓存.磁盘需要的读取次数较少,您的IO时间可专用于为ReadDb写入插入的数据. (这是你的第一次快速运行.)
>您将第二个数据集加载到WriteDb中.在加载操作期间,没有足够的内存来缓存ReadDb中的现有数据和写入WriteDb的新数据.这种内存争用导致WriteDb缓存的页面更少.
>您截断ReadDb.这会使大部分缓存失效(即缓存的50GB ReadDb数据).
>然后,您尝试第二次加载ReadDb.在这里你只有很少的WriteDb缓存,所以你的IO时间在读取WriteDb页面(你的查询)和写入ReadDb页面(你的插入)之间分配. (这是你的第二次慢跑.)
您可以通过比较第一次和第二次加载操作期间的sql Server缓存未命中率来测试此理论.
>为ReadDb / WriteDb使用单独的磁盘阵列以提高并行IO性能.>增加可用缓存(服务器内存量)以适应ReadDb WriteDb的总大小并最大限度地减少缓存未命中.>通过使用MERGE语句而不是一次转储/加载50GB数据,最大限度地减少每个加载操作对现有缓存页面的影响.