Вопрос

У меня есть сложное предложение SQL, которое стало еще сложнее из-за изменения требований.Существует четыре основных набора случаев, каждый из которых имеет различное сочетание других факторов.Более читабельно (на мой взгляд) иметь четыре случая как отдельные ветви предложенияwhere и повторять избыточные критерии в каждой ветви.Но я не знаю, насколько хорошо механизм базы данных это оптимизирует.

Вот выражение в его избыточной форме.Я заменил фактические критерии буквами.A — критерий «ветвления», который существует в четырех формах.Все выражения имеют вид field='value', если иное не отмечено.

A1 AND B AND C AND D
OR A2 AND B AND C AND D AND E AND F1 AND G
OR A3 AND A3a AND B AND C AND D AND E AND F1 AND G
OR A4 AND B AND C AND D AND F2

Все буквы А, кроме А4, имеют форму field in ('value1','value2').D есть field > 'value'.G имеет форму field not in (subquery).

Вот выражение, преобразованное в (я думаю) его наименее избыточную форму.

B AND C AND D AND (
    A1
    OR (
        E AND F1 AND G AND (
            A2
            OR (A3 AND A3a)
        )
    )
    OR (A4 AND F2)

Мой вопрос в том, следует ли мне разложить это выражение на самое простое (наименее избыточное) логичный форме, или можно ли сохранить ее в более избыточной, но при этом более читаемой форме.Целевой базой данных является Sybase, но мне хотелось бы знать ответ для RDMBS в целом.

Это было полезно?

Решение

В RDBMS world Я бы не стал особо беспокоиться об избыточности, здесь важнее эффективность.

В твоем случае я бы UNION все четыре запроса с использованием Aв качестве верхнего условия, например:

SELECT  *
FROM    mytable
WHERE   A1 AND B AND C
UNION
SELECT  *
FROM    mytable
WHERE   A2 AND B AND C AND D AND E AND F1 AND G
…

я не заглядывал Sybase для более чем 7 лет, но во всех основных RDBMS's UNIONболее эффективны, чем ORх.

См. эту статью в моем блоге, чтобы узнать о подходе к подобной проблеме в Oracle:

а также эта статья для сравнения UNION против OR в MySQL:

Я думаю, что эти подходы будут хорошо работать для Sybase слишком.

Вам также необходимо создать индексы для столбцов, используемых в ваших условиях, чтобы получить выгоду от UNION's

Обновлять:

Поскольку условие G является подзапросом, возможно, ему понадобится HASH JOIN выполнять быстро. HASH JOIN требуется полное сканирование всех нефильтрованных значений, поэтому, возможно, лучше отфильтровать все значения за одно полное сканирование, а затем выполнить HASH JOIN:

SELECT  *
FROM    (
        SELECT  *
        FROM    foo
        WHERE   condition_set_1
        UNION
        SELECT  *
        FROM    foo
        WHERE   condition_set_2_but_no_g
        …
        ) q
WHERE   G

Чтобы сделать какие-либо дальнейшие выводы, на самом деле будет гораздо лучше увидеть сам запрос.

Другие советы

Если бы я решал эту проблему на M$ SQL Server, я бы написал ее так, как хотел, и посмотрел бы на план выполнения запроса.Если бы он (а) работал медленно и (б) имел плохой план выполнения, я бы провел рефакторинг и документировал.Не уверен, какой в ​​Sybase механизм просмотра того, КАК оптимизатор выполняет запрос.

Я бы провел рефакторинг.В конце концов, дублированная логика приведет к проблемам.Понимание второго примера может занять на пару секунд больше времени, но в большом объеме вещей легче увидеть, что происходит, поскольку вы можете быстро просмотреть весь операторwhere и начать определять, что на что влияет.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top