Сложный SQL, где предложение: нужно ли фактор логики - PullRequest
0 голосов
/ 27 апреля 2009

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

Вот выражение в его избыточной форме. Я заменил фактические критерии на буквы. А - это критерий «ветвления», который представлен в четырех формах. Все выражения имеют вид 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 в целом.

Ответы [ 3 ]

2 голосов
/ 27 апреля 2009

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

2 голосов
/ 27 апреля 2009

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

В вашем случае я бы 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 UNION более эффективны, чем OR.

См. Эту статью в моем блоге для подхода к проблеме силимара в Oracle:

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

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

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

Обновление:

Поскольку условие 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

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

0 голосов
/ 27 апреля 2009

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

...