Long select 显示结果需要55秒,有更好的方法请教?

Long select is taking 55 secs to display the result, better way to consult?

简介

大家好,我正在尝试获取较大的 select,但我遇到了一个主要问题,此查询需要 55 秒才能显示 13,000 行,因为有 4 sub-query (搜索相同的 table)它们是:

  1. PARENT LINK 所以自动
  2. PARENT LINK 所以行 AUT
  3. PLSO 自动创建日期
  4. PLSO 自动发货日期

这4列只有在DEM_TYPE'WO'时才会获取数据,所以我才放入每个 sub-query CASE WHEN.

如果 DEM_TYPE 不是 'WO' 那 4 列将为 NULL

我只需要在 sub-query 中找到的第一行,这就是我使用 TOP 1 的原因。

接下来我将向您展示 table

的查询和结果
CREATE UNIQUE INDEX  IDX_TMP
    ON ENT_DEMAND_SUPPLY(ROWID);
    SELECT ONE.ROWID, ONE.PLANNER, ONE.BUYER, ONE.DEM_TYPE, ONE.DEM_SOURCE, ONE.DEM_SOURCE_LINE, ONE.DEM_PART_ID, ONE.[PART ID DESCRIPTION], ONE.DEM_QTY, ONE.ACUM_ASSIGN_QTY, ONE.ASSIGNED_QTY, ONE.SUPPLY_TYPE, ONE.SUPPLY_SOURCE, ONE.SUPPLY_SOURCE_LINE, ONE.SUPPLY_QTY, ONE.REST_QTY, ONE.SUPPLIER, ONE.[PO STATUS], ONE.[WO STATUS],   ONE.[SO CREATED DATE], ONE.[WO CREATED DATE], ONE.[SO PROMISE SHIP DATE PER LINE], ONE.[WO RELEASE DATE], ONE.[PO PLACE DATE], ONE.[SITE ARRIVAL], ONE.[UPDATE SHIP DATE], ONE.[INITIAL SHIP DATE], ONE.[LEAD TIME PROVIDE]  AS 'LEAD TIME PROVIDE BY SCHEDULER', ONE.[LEAD TIME REQUIRED TO SUPPLIER], ONE.[LEAD TIME STANDARD], ONE.[QUALITY WAREHOUSE], ONE.COMMENTS, ONE.[SO LINK ERP], ONE.[SO LINE LINK ERP], ONE.[PARENT LINK SO ERP], ONE.[PARENT LINK SO LINE ERP], ONE.PLSO_ERP_CREATE_DATE, ONE.PLSO_ERP_SHIPPED_DATE
    ,CASE WHEN ONE.DEM_TYPE = 'WO' THEN  (SELECT TOP 1 DEM_SOURCE FROM ENT_DEMAND_SUPPLY  WHERE SUPPLY_TYPE = 'WO' AND SUPPLY_SOURCE = ONE.DEM_SOURCE AND SUPPLY_SOURCE_LINE = ONE.DEM_SOURCE_LINE ORDER BY DEM_PART_ID, DEM_DATE) ELSE NULL END AS 'PARENT LINK SO AUT'
    ,CASE WHEN ONE.DEM_TYPE = 'WO' THEN  (SELECT TOP 1 DEM_SOURCE_LINE FROM ENT_DEMAND_SUPPLY  WHERE SUPPLY_TYPE = 'WO' AND SUPPLY_SOURCE = ONE.DEM_SOURCE AND SUPPLY_SOURCE_LINE = ONE.DEM_SOURCE_LINE ORDER BY DEM_PART_ID, DEM_DATE) ELSE NULL END AS 'PARENT LINK SO LINE AUT'
    ,CASE WHEN ONE.DEM_TYPE = 'WO' THEN  (SELECT TOP 1 [PLSO_ERP_CREATE_DATE] FROM ENT_DEMAND_SUPPLY  WHERE SUPPLY_TYPE = 'WO' AND SUPPLY_SOURCE = ONE.DEM_SOURCE AND SUPPLY_SOURCE_LINE = ONE.DEM_SOURCE_LINE ORDER BY DEM_PART_ID, DEM_DATE) ELSE NULL END AS 'PLSO AUT CREATED DATE'
    ,CASE WHEN ONE.DEM_TYPE = 'WO' THEN  (SELECT TOP 1 [PLSO_ERP_SHIPPED_DATE] FROM ENT_DEMAND_SUPPLY  WHERE SUPPLY_TYPE = 'WO' AND SUPPLY_SOURCE = ONE.DEM_SOURCE AND SUPPLY_SOURCE_LINE = ONE.DEM_SOURCE_LINE ORDER BY DEM_PART_ID, DEM_DATE) ELSE NULL END AS 'PLSO AUT SHIPPED DATE'
    FROM ENT_DEMAND_SUPPLY ONE
    ORDER BY ONE.DEM_PART_ID, ONE.DEM_DATE
    DROP INDEX ENT_DEMAND_SUPPLY.IDX_TMP

Table result part 1 Table result part 2

如您所见,在第 1 行。 8 DEM_TYPE 是 'WO',DEM_SOURCE 的值为 12900,DEM_SOURCE_LINE 值为 1(table 结果第 1 部分)所以在这种情况下 4 sub-query 将 运行(table 结果第 2 部分)

*图中编号2 ,列 PLSO AUT CREATED DATEPLSO AUT SHIPPED DATE 为 NULL,这是有效的,因为它可以存在或不存在这些记录


Sub-Query逻辑

这东西的逻辑是:我要在SUPPLY_SOURCE中找到DEM_SOURCE,在整个table中找到DEM_SOURCE_LINE IN SUPPLY_SOURCE_LINE,我的意思是,例如我们 return 到第 8 行。

如果我们取行号。 8 我们有这些值... DEM_TYPE = 'WO', DEM_SOURCE: 12900 和 DEM_SOURCE_LINE = 1, 我可以让 sub-query 准备好搜索和像这样获取该行的 4 个额外列:

(SELECT TOP 1 DEM_SOURCE FROM ENT_DEMAND_SUPPLY  WHERE SUPPLY_TYPE = 'WO' AND SUPPLY_SOURCE = '12900' AND SUPPLY_SOURCE_LINE = '1')

Sub-query result

如果你检查图片编号。 2,这 4 个值将在最后 4 列中,其中包含我们在开头讨论的 4 个名称......当 DEM_TYPE 为 'WO' 时,我必须为每一行执行这些过程,有人知道我该如何改进它?我尝试使用索引,它有帮助但速度不够快。 非常感谢您花时间阅读这篇文章 post,如果您有任何问题或建议,请告诉我!

在我看来,在一个查询中加载所有数据是一种不好的做法。如果是延迟加载在某处缓存数据,那么也许这是可以接受的,但如果您尝试为用户加载数据,那么分页将是更好的选择。

我希望您为 SUPPLY_TYPESUPPLY_SOURCESUPPLY_SOURCE_LINE 创建索引,因为它可以缩短查询时间。

对于您的问题,您可以使用 OUTER APPLY - Sql server cross apply and outer apply

我未经测试的快速回复是(仍有 space 需要修改):

SELECT
    ONE.ROWID, ONE.PLANNER, ONE.BUYER, ONE.DEM_TYPE, ONE.DEM_SOURCE, ONE.DEM_SOURCE_LINE, ONE.DEM_PART_ID, ONE.[PART ID DESCRIPTION], ONE.DEM_QTY, ONE.ACUM_ASSIGN_QTY, ONE.ASSIGNED_QTY, ONE.SUPPLY_TYPE, ONE.SUPPLY_SOURCE, ONE.SUPPLY_SOURCE_LINE, ONE.SUPPLY_QTY, ONE.REST_QTY, ONE.SUPPLIER, ONE.[PO STATUS], ONE.[WO STATUS],   ONE.[SO CREATED DATE], ONE.[WO CREATED DATE], ONE.[SO PROMISE SHIP DATE PER LINE], ONE.[WO RELEASE DATE], ONE.[PO PLACE DATE], ONE.[SITE ARRIVAL], ONE.[UPDATE SHIP DATE], ONE.[INITIAL SHIP DATE], ONE.[LEAD TIME PROVIDE]  AS 'LEAD TIME PROVIDE BY SCHEDULER', ONE.[LEAD TIME REQUIRED TO SUPPLIER], ONE.[LEAD TIME STANDARD], ONE.[QUALITY WAREHOUSE], ONE.COMMENTS, ONE.[SO LINK ERP], ONE.[SO LINE LINK ERP], ONE.[PARENT LINK SO ERP], ONE.[PARENT LINK SO LINE ERP], ONE.PLSO_ERP_CREATE_DATE, ONE.PLSO_ERP_SHIPPED_DATE
    ,CASE WHEN ONE.DEM_TYPE = 'WO' THEN [Table2].[DEM_SOURCE] ELSE NULL END AS 'PARENT LINK SO AUT'
    ,CASE WHEN ONE.DEM_TYPE = 'WO' THEN [Table2].[DEM_SOURCE_LINE] ELSE NULL END AS 'PARENT LINK SO LINE AUT'
    ,CASE WHEN ONE.DEM_TYPE = 'WO' THEN [Table2].[PLSO_ERP_CREATE_DATE] ELSE NULL END AS 'PLSO AUT CREATED DATE'
    ,CASE WHEN ONE.DEM_TYPE = 'WO' THEN [Table2].[PLSO_ERP_SHIPPED_DATE] ELSE NULL END AS 'PLSO AUT SHIPPED DATE'
FROM
    ENT_DEMAN_SUPPLY ONE
OUTER APPLY(
    SELECT TOP 1
        DEM_SOURCE
        ,DEM_SOURCE_LINE
        ,PLSO_ERP_CREATE_DATE
        ,PLSO_ERP_SHIPPED_DATE
    FROM
        ENT_DEMAND_SUPPLY [TWO]
    WHERE --These columns should be indexed
        [TWO].SUPPLY_TYPE = 'WO'
        AND [TWO].SUPPLY_SOURCE = ONE.DEM_SOURCE
        AND [TWO].SUPPLY_SOURCE_LINE = ONE.DEM_SOURCE_LINE
) [Table2]
ORDER BY ONE.DEM_PART_ID, ONE.DEM_DATE