【发布时间】:2018-05-01 22:48:55
【问题描述】:
SQL 向导和大师的问题。我必须缩短这头野兽的执行时间。执行需要 5 分钟以上,有时会超时。我需要帮助了解如何提高效率。我要返回大约 100,000 行。
场景是:我正在尝试识别应该标记为“约会季节”的“有效订单”。这些订单将包含与有效“类别代码”相关联的商品 (dbo.DTITEMS ON od.CATEGORY = dbo.DTITEMS.CATEGORY)。
然后我使用这个查询的结果基本上用当前“约会季节”的值更新了一个订单字段“DTGSEASON”。
我引用了一个名为 DATING 的表(独立于 CRM.Dbo.Dating),其中存储了促销开始和结束日期、当前约会季节等参数。
这是我正在运行以查找“有效订单”的查询,称为 vDatingValidOrdersReg:
SELECT
h.CUSTOMER
, h.ORDNUMBER
, h.INVNETWTX
, dtgseason.VALUE AS dtgseason
, c.comp_dqdatingmin
, dbo.DTITEMS.ALTMINIMUM
, d.dat_datingapprovedon
, d.dat_ordsincepromostart
, h.EXPDATE
, dbo.DATING.PROMOSTART
, d.dat_season
, d.dat_year
, od.ITEM
, od.CATEGORY
, d.dat_DatingID
, c.Comp_Name
, d.dat_state
, h.ORDUNIQ
, c.comp_dqdatingmax
FROM CRM.dbo.Dating AS d
INNER JOIN CRM.dbo.Company AS c
ON d.dat_CompanyId = c.Comp_CompanyId
LEFT OUTER JOIN dbo.OEORDH AS h
ON c.Comp_IdCust = h.CUSTOMER
LEFT OUTER JOIN dbo.OEORDHO AS dtgseason
ON h.ORDUNIQ = dtgseason.ORDUNIQ AND dtgseason.OPTFIELD = 'dtgseason'
INNER JOIN dbo.OEORDD AS od
ON h.ORDUNIQ = od.ORDUNIQ
INNER JOIN dbo.DTITEMS
ON od.CATEGORY = dbo.DTITEMS.CATEGORY
INNER JOIN dbo.DATING
ON d.dat_season = dbo.DATING.SEASON
AND d.dat_year = dbo.DATING.YEAR
AND dbo.DTITEMS.SEASON = dbo.DATING.SEASON
AND dbo.DTITEMS.YEAR = dbo.DATING.YEAR
WHERE (h.ORDDATE BETWEEN dbo.DATING.PROMOSTART AND dbo.DATING.PROMOEND)
AND (h.EXPDATE BETWEEN dbo.DATING.EXPSHIPST AND dbo.DATING.EXPSHIPEND)
AND (d.dat_state = 'Approve')
AND (d.dat_Deleted IS NULL)
AND (dbo.DATING.SEASCLOSED = 0)
AND (dbo.DTITEMS.ALTMINIMUM = 0)
AND (h.ORDNUMBER NOT IN (
SELECT ORDNUMBER
FROM dbo.vDatingValidOrdersAlt))
AND (dbo.DATING.ORDERON = 1)
这是它引用的查询,它基本上是相同的,但查找具有不同项目类别的订单:vDatingValidOrdersAlt。这是我的问题吗?
SELECT
h.CUSTOMER
, h.ORDNUMBER
, h.INVNETWTX
, dtgseason.VALUE AS dtgseason
, c.comp_dqdatingmin
, dbo.DTITEMS.ALTMINIMUM
, d.dat_datingapprovedon
, d.dat_ordsincepromostart
, h.EXPDATE
, dbo.DATING.PROMOSTART
, d.dat_season
, d.dat_year
, od.ITEM
, od.CATEGORY
, d.dat_DatingID
, c.Comp_Name
, d.dat_state
, h.ORDUNIQ, c.comp_dqdatingmax
FROM CRM.dbo.Dating AS d
INNER JOIN CRM.dbo.Company AS c
ON d.dat_CompanyId = c.Comp_CompanyId
LEFT OUTER JOIN dbo.OEORDH AS h
ON c.Comp_IdCust = h.CUSTOMER
LEFT OUTER JOIN dbo.OEORDHO AS dtgseason
ON h.ORDUNIQ = dtgseason.ORDUNIQ AND dtgseason.OPTFIELD = 'dtgseason'
INNER JOIN dbo.OEORDD AS od
ON h.ORDUNIQ = od.ORDUNIQ
INNER JOIN dbo.DTITEMS
ON od.CATEGORY = dbo.DTITEMS.CATEGORY
INNER JOIN dbo.DATING
ON d.dat_season = dbo.DATING.SEASON
AND d.dat_year = dbo.DATING.YEAR
AND dbo.DTITEMS.SEASON = dbo.DATING.SEASON
AND dbo.DTITEMS.YEAR = dbo.DATING.YEAR
WHERE (h.ORDDATE BETWEEN dbo.DATING.PROMOSTART AND dbo.DATING.PROMOEND)
AND (h.EXPDATE BETWEEN dbo.DATING.EXPSHIPST AND dbo.DATING.EXPSHIPEND)
AND (d.dat_state = 'Approve')
AND (d.dat_Deleted IS NULL)
AND (dbo.DATING.SEASCLOSED = 0)
AND (dbo.DTITEMS.ALTMINIMUM > 0)
AND (dbo.DATING.ORDERON = 1)
必须有一种方法可以减少此查询的资源密集型,但我不知道如何去做。有什么想法和建议?
【问题讨论】:
-
请考虑在格式化查询时更好地使用空格。这些查询很难阅读,因为所有内容都浓缩为几行。作为查询的表现。您需要为表、索引以及查询计划提供 DDL。如果没有所有这些,我们将无法告诉您如何有效地改进查询。
-
此外,您的查询中有一些
LEFT OUTER JOINs,但是,请在您的WHERE中引用该对象(例如h.EXPDATE)。这隐含地将LEFT OUTER JOIN转换为INNER JOIN。这是故意的吗?如果是这样,您应该使用INNER JOIN,如果不是,您需要解决您的WHERE或ON子句.. -
@Larnu 我试过了...编辑:看起来 Sean Lange 也尝试了格式化哈哈。
-
@JacobH 比以前好多了。现在我们只需要等待 DDL、查询计划、索引详细信息,以及为什么 OP 在
WHERE子句中使用OR子句和IS NULL表达式引用具有LEFT JOIN的对象;这意味着它不再是LEFT JOIN。有几个问题要他们回答。 :) -
如果第二个查询是您在第一个查询中选择的视图,则您不需要返回除
ORDNUMBER之外的任何列。这是一个简单的性能提升。我会创建一个辅助视图,它只为您的NOT IN子句返回一列。
标签: sql sql-server database