调整SQL查询

时间:2014-01-23 11:25:32

标签: sql sql-server performance sql-tuning

我正在尝试调整以下查询,该查询对INVENTTABLE有500k IO,我认为这是一个很好的起点。所有联接的复杂性已经打败了我,但我无法绕过一个良好的开端,这会是什么?

提前感谢任何提示。

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

2 个答案:

答案 0 :(得分: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 ID,然后再加入?在连接条件中使用udf和case语句可能不是最好的主意。

答案 1 :(得分:0)

你想看看可创造性的想法是好的。很明显,结果中没有显示任何字段,也不需要将其作为连接其他两个表的链接。因此,只有在那里才能保证存在适当的可发明记录。这可以在EXISTS条款中完成。

然后检查为什么有两个几乎相似的连接与UNION ALL粘合。所有表都被访问两次。这有必要吗?有一次你想要所有的sl.salesqty&lt; 0并通过stl.subsalesid = st.marimssalesid链接。另一次你想要所有的sl.salesqty&gt; 0并通过stl.subsalesid = st.salesid链接。也许你可以做一个select语句并只访问每个表一次。

结果有一个salestable(st)字段。这是st.DATAAREAID。但实际上这是一个搜索和连接标准,因此您可以用sl.DATAAREAID或甚至文字'adf'替换它。所以表格中没有字段。也许也只是一个存在的东西?

同样,当salestable再次被读为st1时。它不是所选列的一部分,因此它可以转换为EXISTS子句。

这只是第一眼看到的,所以我可能会在这里和那里弄错。它只是给你一些东西开始。