2014-01-23 2 views
-2

Я пытаюсь настроить следующий запрос, который получил 500k IO против INVENTTABLE, который, как я думал, станет хорошим местом для начала. Сложность всех объединений избила меня, хотя я не смог обернуться вокруг, где хорошее начало было бы с этим?Настройка SQL-запроса

Заранее благодарим за любые советы.

SET STATISTICS IO ON 

DECLARE 
@paramCompany  varchar(3), 
@paramCreatedBy  varchar(8000), 
@paramCustomer  varchar(100), 
@paramBlanketId  varchar(20) 

SET @paramCompany = 'adf' 
SET @paramCreatedBy = 'All' 
SET @paramCustomer = NULL 
SET @paramBlanketId = NULL 

SELECT 
un.MAINSALESID, 
un.DATAAREAID, 
Sum(un.Quantity) as 'Quantity', 
Sum(un.SalesValue) as 'SalesValue' 
INTO #desprel 
FROM 
(SELECT 
    stl.MAINSALESID, 
    st.DATAAREAID, 
    sl.SALESQTY as 'Quantity', 
    sl.SALESQTY * sl.SALESPRICE as 'SalesValue' 
FROM 
    DynamicsV5Realtime.dbo.SALESTABLE st 
INNER JOIN 
    DynamicsV5Realtime.dbo.SALESLINE sl 
ON 
    sl.SALESID = st.SALESID 
    and sl.DATAAREAID = st.DATAAREAID 
INNER JOIN 
    DynamicsV5Realtime.dbo.INVENTTABLE it 
ON 
    it.ITEMID = sl.ITEMID 
    and it.DATAAREAID = sl.DATAAREAID 
INNER JOIN 
    DynamicsV5Realtime.dbo.SALESTABLELINKS stl 
ON 
    stl.SUBSALESID = st.SALESID 
    and stl.DATAAREAID = st.DATAAREAID 
INNER JOIN 
    DynamicsV5Realtime.dbo.SALESTABLE st1 
ON 
    st1.SALESID = stl.MAINSALESID 
    and st1.SALESTYPE = 5 
--to get Order created by 
inner JOIN 
    --TR 
    vw_R000_EmployeeList pm 
ON 
    --st1.SALESTAKER = pm.emplid 
    CASE WHEN st1.SALESTAKER = 'balla' THEN 'gende' ELSE st1.SALESTAKER END = pm.emplid 
    and (pm.[NAME] in (SELECT * FROM  udf_MultiValueParameterHandlingString(@paramCreatedBy)) or @paramCreatedBy = 'All') 
WHERE 
    st.DATAAREAID = 'adf' 
    and st.SALESTYPE = 3 -- Release Order 
    and st.SALESSTATUS in (2,3) 
    and sl.SALESSTATUS <> 4 
    and it.ITEMGROUPID <> 'G0022A' 
    and sl.SALESQTY > 0 
    and st1.CUSTACCOUNT = IsNull(@paramCustomer,st1.CUSTACCOUNT) 
    and st1.SALESID = IsNull(@paramBlanketId,st1.SALESID) 
UNION ALL 
SELECT 
    stl.MAINSALESID, 
    st.DATAAREAID, 
    sl.SALESQTY as 'Quantity', 
    sl.SALESQTY * sl.SALESPRICE as 'SalesValue' 
FROM 
    DynamicsV5Realtime.dbo.SALESTABLE st 
INNER JOIN 
    DynamicsV5Realtime.dbo.SALESLINE sl 
ON 
sl.SALESID = st.SALESID 
and sl.DATAAREAID = st.DATAAREAID 
INNER JOIN 
    DynamicsV5Realtime.dbo.INVENTTABLE it 
ON 
    it.ITEMID = sl.ITEMID 
    and it.DATAAREAID = sl.DATAAREAID 
INNER JOIN 
    DynamicsV5Realtime.dbo.SALESTABLELINKS stl 
ON 
    stl.SUBSALESID = st.MARIMSSALESID 
    and stl.DATAAREAID = st.DATAAREAID 
INNER JOIN 
    DynamicsV5Realtime.dbo.SALESTABLE st1 
ON 
    st1.SALESID = stl.MAINSALESID 
    and st1.SALESTYPE = 5 
--to get Order created by 
inner JOIN 
--TR 
    vw_R000_EmployeeList pm 
ON 
--st1.SALESTAKER = pm.emplid 
    CASE WHEN st1.SALESTAKER = 'balla' THEN 'gende' ELSE st1.SALESTAKER END = pm.emplid 
and (pm.[NAME] in (SELECT * FROM udf_MultiValueParameterHandlingString(@paramCreatedBy)) or @paramCreatedBy = 'All') 
WHERE 
    st.DATAAREAID = 'adf' 
    and st.SALESTYPE = 3 -- Release Order 
    and st.SALESSTATUS in (2,3) 
    and sl.SALESSTATUS <> 4 
    and it.ITEMGROUPID <> 'G0022A' 
    and sl.SALESQTY < 0 
    and st1.CUSTACCOUNT = IsNull(@paramCustomer,st1.CUSTACCOUNT) 
    and st1.SALESID = IsNull(@paramBlanketId,st1.SALESID)  
      ) un 
GROUP BY 
un.MAINSALESID, 
un.DATAAREAID 
+0

Возможно, вы захотите отметить как SQL Server, поскольку настройка может быть довольно специфичной для РСУБД. –

+1

Да. Предполагая, что это IS Sql Server, запустите запрос в SSMS и скажите ему, чтобы он создал план запроса. Что я делаю, тогда он ищет операцию с наивысшим% и пытается ее оптимизировать. Также SSMS иногда предлагает новые индексы, которые помогут: их применение, как правило, хорошо! –

+0

Да, я смотрю план выполнения, и один из самых больших запросов индекса относится к таблице DIRPARTYCOMMUNICATIONRELA - это должна быть какая-то внутренняя рабочая таблица, поэтому не знаете, как я могу ее индексировать. Я надеялся на какую-то помощь в том, как переписать запрос, чтобы снизить общий объем IO, поэтому я могу применить эту технику в другом месте. – Tom

ответ

0

Ваша идея взглянуть на придуманный товар хороша. Очевидно, что ни одно из его полей не показано в результатах, и оно не требуется в качестве ссылки для объединения двух других таблиц. Таким образом, существует только гарантия того, что существует соответствующая запись в изобретении. Это можно сделать в предложении EXISTS.

Затем проверьте, почему есть два почти похожих соединения, склеенных с UNION ALL. Доступ ко всем таблицам осуществляется дважды. Это необходимо? Один раз вы хотите, чтобы все sl.salesqty < 0 и вы связывались через stl.subsalesid = st.marimssalesid. В другой раз вы хотите, чтобы все sl.salesqty> 0 и вы связывались через stl.subsalesid = st.salesid. Возможно, вы можете сделать это один оператор select и получить доступ к каждой таблице только один раз.

Результат имеет одно поле для покрытия (st). Это st.DATAAREAID. Но это критерий поиска и присоединения на самом деле, поэтому вы можете заменить его либо sl.DATAAREAID, либо даже буквенным «adf». Таким образом, нет поля из таблицы st. Может быть, и только СУЩЕСТВУЮЩАЯ вещь?

То же самое снова, когда salestable снова считывается как st1. Он не является частью выбранных столбцов, поэтому, возможно, он может быть преобразован в предложение EXISTS.

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

+0

Спасибо за это. В точке EXISTS я должен заменить соединение условием EXISTS? Я не вижу, как я мог бы еще, как я могу фильтровать запись. Предложите ли вы пример того, как это сделать? Я обещаю, что я пытаюсь понять это, а не просто заставить вас переписать его для меня. – Tom

+0

Вы полностью удаляете соединение и добавляете предложение accordant exists к предложению where: ... и существует (выберите * из DynamicsV5Realtime.dbo.INVENTTABLE, где it.ITEMID = sl.ITEMID и it.DATAAREAID = sl.DATAAREAID и и it.ITEMGROUPID <> 'G0022A') –

+0

OK Я пробовал, что, к сожалению, это увеличило количество ввода-вывода, а также время, затраченное на выполнение :( – Tom

1

Является ли это только мной или этот конкретный раздел немного запутанным? Я бы занялся этим первым.

inner JOIN 
    --TR 
    vw_R000_EmployeeList pm 
ON 
    --st1.SALESTAKER = pm.emplid 
    CASE WHEN st1.SALESTAKER = 'balla' THEN 'gende' ELSE st1.SALESTAKER END = pm.emplid 
    and (pm.[NAME] in (SELECT * FROM udf_MultiValueParameterHandlingString(@paramCreatedBy)) or @paramCreatedBy = 'All') 

Можете ли вы пытаетесь с помощью временной таблицы, чтобы выяснить заранее в SALESTAKER идентификаторам, а затем присоединиться к этому? Использование утверждения udf и case в условии соединения, вероятно, не самая лучшая идея.

+0

Да, я, наверное, должен расколоть это – Tom

Смежные вопросы