2017-08-24 40 views
0

我已经创建了一个正在进行数百万行数据的批量插入的查询。 运行此查询时,我收到了一个temdb内存错误。以百万数据批量插入的T-SQL性能问题

这是查询:

INSERT INTO ods.contact_method (cmeth_cust_id, cmeth_chan_type_id, cmeth_address_id, 
           cmeth_identifier, cmeth_active, cmeth_review_date, 
           cmeth_last_validated, cmeth_updatesrc_id, cmeth_updated_date) 
    SELECT 
     custpers_cust_id, 5, ad.adet_id, 
     COALESCE(street3, '') + ' ' + COALESCE(street2, '') + ' ' 
     + COALESCE(housenumber, '') + ' ' + COALESCE(street, ''), 
     CASE custpers_status 
      WHEN 'InActive' THEN 'N' 
      ELSE 'Y' 
     END, 
     Dateadd(year, 2, last_update_date), 
     last_update_date, 1, Getdate() 
    FROM 
     ods.address_detail (nolock) ad 
    JOIN 
     ods.customer_persona (nolock) cp ON cp.custpers_cust_id = ad.adet_updated_by 
    JOIN 
     ods.tempcust_address_insert (nolock)tp ON tp.bvoc = cp.custpers_bvoc_id 
    WHERE 
     NOT EXISTS (SELECT 1 
        FROM ods.contact_method (nolock) cm 
        WHERE cm.cmeth_cust_id = cp.custpers_cust_id 
         AND cm.cmeth_address_id IS NOT NULL 
         AND ad.adet_id = cm.cmeth_address_id) 

我需要帮助优化这个查询;我应该使用左连接还是不存在条件数百万的数据进行批量插入?

+1

问题寻求帮助的性能应包括DDL,DML的中包含测试数据的表格。如果测试数据很大,请尝试脚本化表格的模式和统计信息('右键单击数据库 - >生成脚本 - >选择特定数据库对象 - >在下一个屏幕中选择高级并选择脚本统计信息)'粘贴它的问题。有了这个信息任何一个repro你面临的同样的问题。否则它变得很难回答你的问题.Pasting server versio n也有帮助 – TheGameiswar

+0

['NOT EXISTS'比'LEFT JOIN'更好](https://sqlperformance.com/2012/12/t-sql-queries/left-anti-semi-join)。你在说几百万行,有几百万,还是几亿?你能发布执行计划吗?你的桌子上有什么索引?此外,你可能希望阅读这个 - [坏习惯:把NOLOCK无处不在](https://blogs.sentryone.com/aaronbertrand/bad-habits-nolock-everywhere/)。 – GarethD

+1

这绝对不是*批量插入操作。这是一个普通的旧的,完全记录的INSERT。 “NOLOCK”的意思是“给我脏数据”,而不是“走得快”。什么是执行计划?那里有什么指数? –

回答

-1

你得到的内存错误临时数据库可由于低于2 issues-

1)您的查询是有性能问题,并选择不必要的数据。 - 我不能在不知道表结构,索引,碎片和数据大小的情况下对此进行评论。然而改变是否存在条件LEFT JOIN必然有助于提高性能 -

FROM ods.address_detail (nolock) ad 
    JOIN ods.customer_persona (nolock) cp 
    ON cp.custpers_cust_id = ad.adet_updated_by 
    JOIN ods.tempcust_address_insert (nolock)tp 
    ON tp.bvoc = cp.custpers_bvoc_id   
left join contact_method cm (nolock) 
on cm.cmeth_cust_id = cp.custpers_cust_id 
AND ad.adet_id = cm.cmeth_address_id 
AND cm.cmeth_address_id IS NOT NULL -- not sure if this condtion is required 
Where cm.cmeth_cust_id is null -- add all primary key columns of contact_method here 

2)临时数据库内存错误也随之到来,如果您选择的是大量的数据作为比较临时数据库大小 - 来解决这个问题您可以在插入数据时使用'top',并在插入查询中多次运行相同的查询和左连接条件,以确保不会插入重复的数据。

SELECT top 1000000 -- this will make sure your are selecting limited data 
    custpers_cust_id, 
    5, 
    ad.adet_id, 
    COALESCE(street3, '') + ' ' 
........ 

如果这不是你有使用@@ rowcont值插入数据写了一个循环中的一次活动 -

while COUNT(@count>0) 
begin 

    <your insert statement wiht select top > 
    set @count = @@ROWCOUNT  
end