2012-02-09 41 views
2

有一个旧的SSIS包,每天都会从Oracle向我们的Sql Server数据库提取大量数据。数据被插入到一个非规范化的数据库中,并且我正在处理一个存储过程来选择这些数据,并将其插入到规范化数据库中。 Oracle数据库过度标准化,所以我写的查询最终有12个内部连接来获取我需要的所有列。另一个问题是我正在处理大量的数据。我选择的一张桌子有超过1200万条记录。这是我的查询:处理大量数据,并在SQL Server 2008中处理12个内部连接的查询

Declare @MewLive Table 
(

UPC_NUMBER VARCHAR(50), 
ITEM_NUMBER VARCHAR(50), 
STYLE_CODE VARCHAR(20), 
COLOR VARCHAR(8), 
SIZE VARCHAR(8), 
UPC_TYPE INT, 
LONG_DESC VARCHAR(120), 
LOCATION_CODE VARCHAR(20), 
TOTAL_ON_HAND_RETAIL NUMERIC(14,0), 
VENDOR_CODE VARCHAR(20), 
CURRENT_RETAIL NUMERIC(14,2) 


) 

INSERT INTO @MewLive(UPC_NUMBER,ITEM_NUMBER,STYLE_CODE,COLOR,[SIZE],UPC_TYPE,LONG_DESC,LOCATION_CODE,TOTAL_ON_HAND_RETAIL,VENDOR_CODE,CURRENT_RETAIL) 
SELECT  U.UPC_NUMBER, REPLACE(ST.STYLE_CODE, '.', '') 
         + '-' + SC.SHORT_DESC + '-' + REPLACE(SM.PRIM_SIZE_LABEL, '.', '') AS ItemNumber, 
         REPLACE(ST.STYLE_CODE, '.', '') AS Style_Code, SC.SHORT_DESC AS Color, 
         REPLACE(SM.PRIM_SIZE_LABEL, '.', '') AS Size, U.UPC_TYPE, ST.LONG_DESC, L.LOCATION_CODE, 
         IB.TOTAL_ON_HAND_RETAIL, V.VENDOR_CODE, SD.CURRENT_RETAIL 
FROM   MewLive.dbo.STYLE AS ST INNER JOIN 
         MewLive.dbo.SKU AS SK ON ST.STYLE_ID = SK.STYLE_ID INNER JOIN 
         MewLive.dbo.UPC AS U ON SK.SKU_ID = U.SKU_ID INNER JOIN 
         MewLive.dbo.IB_INVENTORY_TOTAL AS IB ON SK.SKU_ID = IB.SKU_ID INNER JOIN 
         MewLive.dbo.LOCATION AS L ON IB.LOCATION_ID = L.LOCATION_ID INNER JOIN 
         MewLive.dbo.STYLE_COLOR AS SC ON ST.STYLE_ID = SC.STYLE_ID INNER JOIN 
         MewLive.dbo.COLOR AS C ON SC.COLOR_ID = C.COLOR_ID INNER JOIN 
         MewLive.dbo.STYLE_SIZE AS SS ON ST.STYLE_ID = SS.STYLE_ID INNER JOIN 
         MewLive.dbo.SIZE_MASTER AS SM ON SS.SIZE_MASTER_ID = SM.SIZE_MASTER_ID INNER JOIN 
         MewLive.dbo.STYLE_VENDOR AS SV ON ST.STYLE_ID = SV.STYLE_ID INNER JOIN 
         MewLive.dbo.VENDOR AS V ON SV.VENDOR_ID = V.VENDOR_ID INNER JOIN 
         MewLive.dbo.STYLE_DETAIL AS SD ON ST.STYLE_ID = SD.STYLE_ID 
WHERE  (U.UPC_TYPE = 1) AND (ST.ACTIVE_FLAG = 1) 

该查询几乎崩溃我们的服务器。我试图通过将查询分解为更小的查询来解决问题,但是我使用的临时表变量导致tempdb数据库填充硬盘驱动器。我认为这是因为服务器耗尽内存并崩溃。无论如何要解决这个问题吗?

回答

1

正确的索引一定会帮助

IF

量排在此查询没有结束行的“不计其数”。

尝试以下方法:

  • 加入上dbo.COLOR是如果存在的Fkey上dbo.STYLE_COLOR(COLOR_ID)=> dbo.COLOR(COLOR_ID)

正确指数过度(过度,应当审查)

USE MewLive 
CREATE INDEX ix1 ON dbo.STYLE_DETAIL (STYLE_ID) 
INCLUDE (STYLE_CODE, LONG_DESC) 
WHERE ACTIVE_FLAG = 1 
GO 
CREATE INDEX ix2 ON dbo.UPC (SKU_ID) 
INCLUDE(UPC_NUMBER) 
WHERE UPC_TYPE = 1 
GO 
CREATE INDEX ix3 ON dbo.SKU(STYLE_ID) 
INCLUDE(SKU_ID) 
GO 
CREATE INDEX ix3_alternative ON dbo.SKU(SKU_ID) 
INCLUDE(STYLE_ID) 
GO 
CREATE INDEX ix4 ON dbo.IB_INVENTORY_TOTAL(SKU_ID, LOCATION_ID) 
INCLUDE(TOTAL_ON_HAND_RETAIL) 
GO 
CREATE INDEX ix5 ON dbo.LOCATION(LOCATION_ID) 
INCLUDE(LOCATION_CODE) 
GO 
CREATE INDEX ix6 ON dbo.STYLE_COLOR(STYLE_ID) 
INCLUDE(SHORT_DESC,COLOR_ID) 
GO 
CREATE INDEX ix7 ON dbo.COLOR(COLOR_ID) 
GO 
CREATE INDEX ON dbo.STYLE_SIZE(STYLE_ID) 
INCLUDE(SIZE_MASTER_ID) 
GO 
CREATE INDEX ix8 ON dbo.SIZE_MASTER(SIZE_MASTER_ID) 
INCLUDE(PRIM_SIZE_LABEL) 
GO 
CREATE INDEX ix9 ON dbo.STYLE_VENDOR(STYLE_ID) 
INCLUDE(VENDOR_ID) 
GO 
CREATE INDEX ixA ON dbo.VENDOR(VENDOR_ID) 
INCLUDE(VENDOR_CODE) 
GO 
CREATE INDEX ON dbo.STYLE_DETAIL(STYLE_ID) 
INCLUDE(CURRENT_RETAIL) 

在SELECT列表取代U.UPC_TYPE,1 as UPC_TYPE,

+0

你可以有超过一列上的索引?某些列已经有主键或旧索引集。 – broke 2012-02-09 21:46:12

+0

@broke是的,它是允许的,这些索引可能比集群更好地执行 – 2012-02-10 07:50:31

1

你可以隔离进口 - 通过SKU /位置/供应商/无论什么和批量他们和运行多个查询来获取数据?是否有一个特殊的原因需要在一次碰撞中完成? (除了易于编写查询外)

+0

2个sql数据库之间的表结构完全不同 – broke 2012-02-09 21:14:02

4

您是否尝试过使用真正的表格而不是临时表格。您可以使用SELECT INTO创建一个真实表来存储结果,而不是临时表。

语法是:

SELECT 
    U.UPC_NUMBER, 
    REPLACE(ST.STYLE_CODE, '.', ''). 
    .... 
INTO 
    MEWLIVE 
FROM 
    MewLive.dbo.STYLE AS ST INNER JOIN 
    ... 

该命令将创建表,并可能与您所看到的内存问题有所帮助。

此外,请尝试查看查询分析器中的执行计划,或尝试使用索引调整向导来建议可能有助于加快查询速度的索引。

+0

好建议,我没有考虑使用真正的表。至于索引调整向导,我在哪里可以找到? – broke 2012-02-09 20:19:44

+0

-1表变量与临时表非常相似。临时表的唯一好处 - 您可以单独创建索引并使用临时表统计数据保护。 – 2012-02-09 20:51:51

+1

@OlegDok我认为你曲解了。他建议使用真正的表格,而不是临时表格或表格变量。如果tempdb是一个瓶颈(例如,在较慢的磁盘上,已经过载等),那么在用户数据库中创建永久表(可能在更快的存储上或者不太感到困难)可能会有好处。 – 2012-02-09 23:46:03

2

尝试从Oracle服务器而不是从SQL服务器运行查询。就目前而言,当查询尝试处理时,很可能会通过线路进行大量的通信。

通过预处理连接(也许有一个视图),你只会发送结果。

关于过度规范化:您是否测试过速度是否存在问题?我发现很难相信,它可能是归一化。

+0

您可以使用LinkedServer功能将SQL Server连接到Oracle服务器,然后如果使用OPENQUERY方法,则会在Oracle数据库上处理查询结果传递给SQL。 – Rikalous 2012-02-09 23:18:16