Запрос Postgres не выполняется при наличии оператора WITH

Я применяю сценический драгоценный камень для создания представления базы данных для базы данных Postgres. У меня есть таблица заказов (ops_orders) с записями 73 тыс. И позиция строки заказа (ops_order_line_items), которая принадлежит заказу с записями 170 тыс.

Проблема в том, что в запросе оператор WITH выполняется слишком долго, поэтому он зависает бесконечно:

WITH 
excluded_order_ids AS (
  SELECT ord.id
  FROM ops_orders ord
  WHERE NOT EXISTS (
    SELECT 1
    FROM ops_order_line_items oli
    WHERE oli.processing_status != 6 -- PENDING
      AND oli.order_id = ord.id
    )

  UNION ALL

  SELECT ord.id
  FROM ops_orders ord
  WHERE NOT EXISTS (
    SELECT 1
    FROM ops_order_line_items oli
    WHERE oli.processing_status != 1 -- FULFILLED
      AND oli.order_id = ord.id
    )

  UNION ALL

  SELECT ord.id
  FROM ops_orders ord
  WHERE NOT EXISTS (
    SELECT 1
    FROM ops_order_line_items oli
    WHERE oli.processing_status != 4 -- CANCELLED
      AND oli.order_id = ord.id
    )

  UNION ALL

  SELECT ord.id
  FROM ops_orders ord
  WHERE NOT EXISTS (
    SELECT 1
    FROM ops_order_line_items oli
    WHERE oli.line_item_type != 1 -- RESENT
      AND oli.order_id = ord.id
    )
),
included_order_ids AS (
  SELECT ord.id
  FROM ops_orders ord
  WHERE NOT EXISTS (
    SELECT 1
    FROM ops_order_line_items oli
    WHERE oli.processing_status != 3 -- PENDING
      AND oli.deadline > (current_date + 1)
      AND oli.order_id = ord.id
    )
)

SELECT oli.*
FROM ops_order_line_items oli
JOIN ops_purchase_line_items pli ON pli.id = oli.purchase_line_item_id
JOIN ops_purchase_orders po ON po.id = pli.purchase_order_id
JOIN ops_orders ord ON ord.id = oli.order_id
WHERE ((oli.processing_status IN (0, 2) AND oli.deadline <= (current_date + 3)) -- status: ?, ORDERED
  OR (oli.processing_status IN (5, 7) AND oli.deadline <= current_date) -- status: DROPSHIP, PACKING
    OR (oli.processing_status IN (2) AND po.countdown_date > po.created_at) -- status: FULFILLED
    OR (oli.order_id IN (SELECT id FROM included_order_ids)))
    AND oli.order_id NOT IN (SELECT id FROM excluded_order_ids)
ORDER BY ord.order_number DESC, oli.created_at ASC

Тем не менее, запрос работал, когда я изменил на:

WITH
included_order_ids AS (
  SELECT ord.id
  FROM ops_orders ord
  WHERE NOT EXISTS (
    SELECT 1
    FROM ops_order_line_items oli
    WHERE oli.processing_status != 3 -- PENDING
      AND oli.deadline > (current_date + 1)
      AND oli.order_id = ord.id
    )
)
SELECT oli.*
FROM ops_order_line_items oli
JOIN ops_purchase_line_items pli ON pli.id = oli.purchase_line_item_id
JOIN ops_purchase_orders po ON po.id = pli.purchase_order_id
JOIN ops_orders ord ON ord.id = oli.order_id
WHERE ((oli.processing_status IN (0, 2) AND oli.deadline <= (current_date + 3)) -- status: ?, ORDERED
  OR (oli.processing_status IN (5, 7) AND oli.deadline <= current_date) -- status: DROPSHIP, PACKING
  OR (oli.processing_status IN (2) AND po.countdown_date > po.created_at) -- status: FULFILLED    
  OR (oli.order_id IN (SELECT id FROM included_order_ids)))
  AND oli.order_id NOT IN (
    SELECT ord.id
    FROM ops_orders ord
    WHERE NOT EXISTS (
      SELECT 1
      FROM ops_order_line_items oli
      WHERE oli.processing_status != 6 -- PENDING
        AND oli.order_id = ord.id
      ))
  AND oli.order_id NOT IN (
    SELECT ord.id
    FROM ops_orders ord
    WHERE NOT EXISTS (
      SELECT 1
      FROM ops_order_line_items oli
      WHERE oli.processing_status != 1 -- FULFILLED
        AND oli.order_id = ord.id
      ))
  AND oli.order_id NOT IN (
    SELECT ord.id
    FROM ops_orders ord
    WHERE NOT EXISTS (
      SELECT 1
      FROM ops_order_line_items oli
      WHERE oli.processing_status != 4 -- CANCELLED
        AND oli.order_id = ord.id
      ))
  AND oli.order_id NOT IN (
    SELECT ord.id
    FROM ops_orders ord
    WHERE NOT EXISTS (
      SELECT 1
      FROM ops_order_line_items oli
      WHERE oli.line_item_type != 1 -- RESENT
        AND oli.order_id = ord.id
      ))
ORDER BY ord.order_number DESC, oli.created_at ASC

У оператора WITH в Postgres плохая производительность? Я исследовал, но не нашел никаких упоминаний о плохой работе оператора WITH. Ждем полезного объяснения.

0 ответов

Другие вопросы по тегам