【问题标题】:Oracle query keeps running when the query contains multiple where clauses and aggregate functions当查询包含多个 where 子句和聚合函数时,Oracle 查询继续运行
【发布时间】:2021-04-27 21:20:36
【问题描述】:

我在 oracle 中运行这个选择查询。它一直运行,直到我明确停止它。出现此问题是因为下图中突出显示了聚合函数的最后一个 where 子句条件。

Oracle 查询:

SELECT "DIMLOOKUP_CUSTOMER_CUSTOMER_KEY",
       "DIMLOOKUP_CUSTOMER1_CUSTOMER_KEY",
       "DATE_INVOICE_DATE_KEY_OUTPUT_VALUE",
       "DATE_DELIVERY_DATE_KEY_OUTPUT_VALUE",
       "FACTTABLELOAD_STAGING_WWI_INVOICE_ID",
       "FACTTABLELOAD_STAGING_QUANTITY",
       "FACTTABLELOAD_STAGING_UNIT_PRICE"
FROM
  (SELECT "FACTTABLELOAD_STAGING"."DELIVERY_DATE_KEY" "FACTTABLELOAD_STAGING_DELIVERY_DATE_KEY",
          "FACTTABLELOAD_STAGING"."INVOICE_DATE_KEY" "FACTTABLELOAD_STAGING_INVOICE_DATE_KEY",
          "FACTTABLELOAD_STAGING"."CUSTOMER_WWI_CUSTOMER_ID" "FACTTABLELOAD_STAGING_CUSTOMER_WWI_CUSTOMER_ID",
          "FACTTABLELOAD_STAGING"."CUSTOMERBILLTO_WWI_CUSTOMER_ID" "FACTTABLELOAD_STAGING_CUSTOMERBILLTO_WWI_CUSTOMER_ID",
          "FACTTABLELOAD_STAGING"."WWI_INVOICE_ID" "FACTTABLELOAD_STAGING_WWI_INVOICE_ID",
          "FACTTABLELOAD_STAGING"."QUANTITY" "FACTTABLELOAD_STAGING_QUANTITY",
          "FACTTABLELOAD_STAGING"."UNIT_PRICE" "FACTTABLELOAD_STAGING_UNIT_PRICE",
          "DIMLOOKUP_CUSTOMER"."CUSTOMER KEY" "DIMLOOKUP_CUSTOMER_CUSTOMER_KEY",
          "DIMLOOKUP_CUSTOMER1"."CUSTOMER KEY" "DIMLOOKUP_CUSTOMER1_CUSTOMER_KEY",
          "FACTTABLELOAD_STAGING"."DELIVERY_DATE_KEY" "DATE_DELIVERY_DATE_KEY_INPUT_DATETIME",
          TO_CHAR("FACTTABLELOAD_STAGING"."DELIVERY_DATE_KEY", 'YYYYMMDD') "DATE_DELIVERY_DATE_KEY_OUTPUT_VALUE",
          "FACTTABLELOAD_STAGING"."INVOICE_DATE_KEY" "DATE_INVOICE_DATE_KEY_INPUT_DATETIME",
          TO_CHAR("FACTTABLELOAD_STAGING"."INVOICE_DATE_KEY", 'YYYYMMDD') "DATE_INVOICE_DATE_KEY_OUTPUT_VALUE"
   FROM "STG_FACTTABLELOAD_6364_ASTWK_108" "FACTTABLELOAD_STAGING"
   LEFT OUTER JOIN "WWI_DESTINATION_REGRESSION"."CUSTOMER" "DIMLOOKUP_CUSTOMER" ON ("FACTTABLELOAD_STAGING"."CUSTOMER_WWI_CUSTOMER_ID" = "DIMLOOKUP_CUSTOMER"."WWI CUSTOMER ID")
   LEFT OUTER JOIN "WWI_DESTINATION_REGRESSION"."CUSTOMER" "DIMLOOKUP_CUSTOMER1" ON ("FACTTABLELOAD_STAGING"."CUSTOMERBILLTO_WWI_CUSTOMER_ID" = "DIMLOOKUP_CUSTOMER1"."WWI CUSTOMER ID")
   WHERE "DIMLOOKUP_CUSTOMER1"."VALID TO" =
       (SELECT MAX("VALID TO")
        FROM "WWI_DESTINATION_REGRESSION"."CUSTOMER" "MM"
        WHERE "DIMLOOKUP_CUSTOMER1"."WWI CUSTOMER ID" = "MM"."WWI CUSTOMER ID"
          AND "MM"."VALID TO" <= "FACTTABLELOAD_STAGING"."INVOICE_DATE_KEY")
     AND "DIMLOOKUP_CUSTOMER"."VALID TO" =
       (SELECT MAX("VALID TO")
        FROM "WWI_DESTINATION_REGRESSION"."CUSTOMER" "MMM"
        WHERE "DIMLOOKUP_CUSTOMER"."WWI CUSTOMER ID" = "MMM"."WWI CUSTOMER ID"
          AND "MMM"."VALID TO" <= "FACTTABLELOAD_STAGING"."INVOICE_DATE_KEY")) ;

你能帮我解释一下为什么会这样吗?是某种 Oracle 限制吗?

谢谢

【问题讨论】:

  • 您在查询中使用的列上是否有索引?

标签: sql database oracle


【解决方案1】:

用分析函数替换 CUSTOMER 表上的 3 个自联接。分析函数将您的结果集分解为不同的窗口,并且可以从每个窗口中提取最大值。从概念上讲,这种方法比连接和 MAX 函数更复杂,但它可以通过移除连接来显着提高性能。

我不完全理解你的数据模型,但我认为这样的事情可以工作:

SELECT *
FROM
(
    SELECT
        ...
        MAX
        (
            CASE
                WHEN "DIMLOOKUP_CUSTOMER1"."VALID TO" <= "FACTTABLELOAD_STAGING"."INVOICE_DATE_KEY"
                THEN "DIMLOOKUP_CUSTOMER1"."VALID TO"
                ELSE NULL
            END
        )
        OVER (PARTITION BY "DIMLOOKUP_CUSTOMER1"."WWI CUSTOMER ID") MAX_VALID_TO
    FROM ...
    WHERE ...
)
WHERE "DIMLOOKUP_CUSTOMER1"."VALID TO" = MAX_VALID_TO;

但这个答案只是一个猜测。如果还是有问题,我建议你运行查询,通过查询 GV$SQL 找到 SQL_ID,然后将 SQL_ID 插入select dbms_sqltune.report_sql_monitor('SQL_ID') from dual; 那个报告会准确告诉你查询的哪个操作慢,并提供帮助信息来推断为什么选择该计划。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-30
    • 2015-10-17
    • 1970-01-01
    • 1970-01-01
    • 2020-07-06
    • 2021-09-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多