Работа с большими объемами данных и запрос с 12 внутренними объединениями в SQL Server 2008 - PullRequest
2 голосов
/ 10 февраля 2012

Существует старый пакет служб SSIS, который ежедневно перетаскивает много данных из Oracle в нашу базу данных Sql Server.Данные вставляются в ненормализованную базу данных, и я работаю над хранимой процедурой, чтобы выбрать эти данные и вставить их в нормализованную базу данных.Базы данных Oracle были слишком нормализованы, поэтому в написанном мною запросе было 12 внутренних объединений, чтобы получить все нужные мне столбцы.Другая проблема заключается в том, что я имею дело с большими объемами данных.Одна таблица, из которой я выбираю, содержит более 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 заполнять жесткий диск.Я полагаю, это потому, что серверу не хватает памяти и происходит сбой.Есть ли способ решить эту проблему?

Ответы [ 4 ]

4 голосов
/ 10 февраля 2012

Вы пытались использовать реальную таблицу вместо временной.Вы можете использовать SELECT INTO, чтобы создать реальную таблицу для хранения результатов вместо временной.

Синтаксис будет:

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

Команда создаст таблицу и может помочь спроблемы с памятью, которые вы видите.

Дополнительно попробуйте просмотреть план выполнения в анализаторе запросов или попробуйте мастер настройки индекса, чтобы предложить некоторые индексы, которые могут помочь ускорить запрос.

2 голосов
/ 10 февраля 2012

Попробуйте выполнить запрос с сервера Oracle, а не с сервера SQL.В существующем состоянии, скорее всего, будет много коммуникаций по проводам, поскольку запрос пытается обработать.

Предварительно обработав объединения (возможно, с представлением), вы будете отправлять только результаты.

По поводу чрезмерной нормализации: проверяли ли вы, является ли это проблемойс точки зрения скорости?Мне трудно поверить, что это может быть слишком нормализовано.

1 голос
/ 10 февраля 2012

Надлежащая индексация определенно поможет

IF

количество строк в этом запросе, не превышающее "миллионы" строк.

Попробуйте следующее:

  • Присоединение к dbo.COLOR является чрезмерным, если на dbo есть FKey.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,

1 голос
/ 10 февраля 2012

Можете ли вы разделить импорт - сгруппировать его по SKU / location / vendor / чем угодно и выполнить несколько запросов, чтобы получить данные? Есть ли какая-то особая причина, по которой все это должно пройти через один удар? (кроме простоты написания запроса)

...