Вопрос:

настройка сложных SQL-запросов

sql performance vertica

38 просмотра

2 ответа

361 Репутация автора

Здравствуйте, у меня есть запрос, который занимает много времени для выполнения и потребляет столько ресурсов, запрос похож на это:

WITH first_match AS (
        SELECT t1.name
               , t1.lastname
               , t2.location
        FROM table1 t1
        INNER JOIN
        table2 t2 
        ON t1.name = t2.name
)
, second_match AS (
        SELECT t1.name
                , t1.lastname
                , t2.location
        FROM table1 t1
        INNER JOIN
        table2 t2
        ON t1.name = SUBSTR(t2.name,0,INSTR(t2.name,'-'))
        WHERE REGEXP_LIKE(t2.name,'[-]')
        AND (t1.name, t1.lastname) NOT IN (SELECT name, lastname FROM first_match)
)
, third_match AS (
        SELECT t1.name
                ,t1.lastname
                ,t2.location
        FROM table1 t1
        INNER JOIN
        table2 t2
        ON t1.name = REGEXP_REPLACE(t2.name, 'uselesssuffix', '')
        WHERE REGEXP_LIKE(t1.name, 'uselesssuffix')
        AND (t1.name, t1.lastname) NOT IN (
                                SELECT name, lastname FROM first_match
                                UNION
                                SELECT name, lastname FROM second_match
                                )
)
, fourth_match AS (
        SELECT t1.name
                ,t1.lastname
                ,t2.location
        FROM table1 t1
        INNER JOIN
        table2 t2
        ON t1.name = SUBSTR(t2.name, 0, 7)
        WHERE LENGTH(t2.name) > 6
        AND (t1.name, t1.lastname) NOT IN (
                                SELECT name, lastname FROM first_match
                                UNION
                                SELECT name, lastname FROM second_match
                                UNION
                                SELECT name, lastname FROM third_match
                                )
)
, final_result AS (
SELECT * FROM first_match
UNION
SELECT * FROM second_match
UNION
SELECT * FROM third_match
UNION
SELECT * FROM fourth_match
)
SELECT * FROM final_result;

Если у меня есть две таблицы, и я пытаюсь объединить их, скажем, в 4 возможных условиях, первый CTE содержит результат первого условия, второй содержит записи, не включенные в первое, и соответствует второму условию, а третий содержит остальные, которые также соответствуют третьему условию и т. д., таким образом, использование AND (t1.name, t1.lastname) NOT IN (SELECT name, lastname FROM first_match).. условия, и в конечном итоге я использую UNION для генерации конечного результата, теперь относительно большое количество CTE (5 в данном случае) и большое количество UNION, и условий превращает этот запрос в тяжелый и требует много ресурсов и времени для выполнения, любые идеи о том, есть ли лучший способ реализовать тот же сценарий, но с другим подходом, возможно, в одном CTE

Автор: Elias Ghali Источник Размещён: 29.05.2019 10:40

Ответы (2)


0 плюса

820891 Репутация автора

У вас есть несколько совпадений, которые вы пытаетесь расставить по приоритетам. Одна вещь, чтобы попробовать это серия LEFT JOINс:

SELECT t1.name, t1.lastname,
       COALESCE(t2_1.location, t2_2.location, , . . . )
FROM table1 t1 LEFT JOIN
     table2 t2_1 
     ON t1.name = t2_1.name LEFT JOIN
     table2 t2_2
     ON t1.name = SUBSTR(t2_2.name, 1, INSTR(t2_2.name, '-')) AND
        t2_2.name LIKE '%-%' AND
        t2_1.name IS NULL LEFT JOIN
     table2 t2_3
     ON t1.name = REGEXP_REPLACE(t2_3.name, 'uselesssuffix', '') AND
        t1.name LIKE '%uselesssuffix%' AND
        t2_1.name IS NULL AND
        t2_2.name IS NULL LEFT JOIN
     . . .
WHERE t1.name IS NOT NULL OR
      t2_1.name IS NOT NULL OR
      . . . 

Обратите внимание, что каждое новое условие проверяет, что все предыдущие условия не совпадают.

Автор: Gordon Linoff Размещён: 29.05.2019 10:47

1 плюс

1664 Репутация автора

Я что-то здесь не так понимаю?

В сложном объединении, включающем несколько логических выражений OR-ed вместе, оценка останавливается с первым выражением из тех, которые оцениваются как TRUE.

Так почему бы не это?

    SELECT   t1.name
           , t1.lastname
           , t2.location
    FROM table1 t1
    INNER JOIN
    table2 t2 
    ON t1.name = t2.name
    OR  (    -- REGEXP_LIKE(t2.name,'[-]')
             -- AND t1.name = SUBSTR(t2.name,1,INSTR(t2.name,'-')-1)
         t1.name=SPLIT_PART(t2.name,'-',1)
    )
    OR  (    -- REGEXP_LIKE(t1.name, 'uselesssuffix') 
             -- AND t1.name = REGEXP_REPLACE(t2.name, 'uselesssuffix', '')
         t1.name=SPLIT_PART(t2.name,'uselesssuffix',1)
    )
    OR  (    LENGTH(t2.name) > 6
         AND t1.name = SUBSTR(t2.name, 1, 7)
    )

... и в то время как я был на этом, я пытался уменьшить необходимые вызовы функций ...

И в Vertica SUBSTR () начинается с 1-й, а не с 0-й позиции строки ..: -]

Автор: marcothesane Размещён: 11.06.2019 05:35
Вопросы из категории :
32x32