Оптимизация SQL-запросов (направление оценки условий) - PullRequest
1 голос
/ 05 июля 2011

Допустим, у меня есть словарь из 26000 слов, 1000 слов на букву алфавита.Если я хочу найти все слова, в которых есть «е», я пишу:

SELECT * 
  FROM dict 
 WHERE word LIKE '%e%';

Если бы я хотел свести это слово только к словам, начинающимся с «а», я мог бы изменить подобное условиеили я мог бы сделать это:

SELECT * 
  FROM dict 
 WHERE word LIKE '%e%' 
   AND id < 1000;

Во многих словах есть буква 'e', ​​и поэтому он вернул бы true только для того, чтобы не выполнить второе требование, если условия оцениваются слева направо, но я ожидал бы быстреерезультаты, если условие оценивается справа налево.

Мой вопрос: было бы лучше иметь id < 1000 в качестве первого или второго условия, или это зависит от типа базы данных.

Ответы [ 4 ]

1 голос
/ 05 июля 2011

Было бы неправильно считать id < 1000 эквивалентом

SELECT * FROM dict WHERE word LIKE'a%'.

Если вы спроектируете свою базу данных таким образом, это нарушит форму First Normal. 1NF , а именно: Нет никакого упорядочения строк сверху вниз. Технически нет способа гарантировать, что этот порядок действителен, особенно если вы хотите добавить слово, начинающееся с «А», после того, как вы установили свое начальное состояние.

1 голос
/ 05 июля 2011

Местоположение условия не имеет значения, потребуется такое же количество сканирований (если применимо).Они не анализируются по порядку - оптимизатор определяет, что и когда применяется, на основе статистики таблиц и индексов (если таковые имеются).Эти статистические данные изменяются и могут устареть (именно поэтому обслуживание важно).

0 голосов
/ 05 июля 2011

Попробуйте изменить условия предложения where, а затем сравните планы выполнения.

Это покажет вам разницу, если таковая имеется (я думаю, они будут идентичны, в данном случае)

Суть в том, что в большинстве случаев это не имеет значения. Однако это может изменить план выполнения.

0 голосов
/ 05 июля 2011

Один из ключевых принципов проектирования современных систем управления реляционными базами данных заключается в том, что вы, пользователь, не имеете никакого реального контроля и не говорите о том, как данные на самом деле хранятся на жестком диске СУБД.Это означает, что вы не можете предполагать, что данные (а) хранятся в алфавитном порядке на диске или (б) что при извлечении данных они будут извлечены в алфавитном порядке.Единственный способ быть абсолютно на 100% уверенным в том, что вы получаете данные, которые вам нужны, - это изложить их так, как вы этого хотите, а все остальное - предположение, что однажды может взорваться вам в лицо.

Почемуэто имеет значение?Поскольку ваш запрос предполагает, что данные, которые вы будете получать, будут в алфавитном порядке, начиная с буквы «А» и увеличиваясь.(И это предполагает непротиворечивый случай - как насчет «A» против «a»? Что-нибудь с начальными пробелами или числами? Разные системы по-разному обрабатывают разные данные ...) Исправив это достаточно просто, добавьте предложение ORDER BY, такое как:

select * from dict where word like ("%e%") and id < 1000 order by word;

Конечно, если у вас есть более 1000 слов, начинающихся с «А» и содержащих «е», у вас проблемы ... и если у вас меньше 1000, вы в конечном итогес кучей "B" слов.Попробуйте что-то вроде:

select * from dict where left(word. 1) = "A" and word like ("%e%");

В зависимости от вашей РСУБД и индексации, имеющейся у вас в таблице, система может сначала идентифицировать все слова «А», а затем выполнить «содержит e »."Отметьте только их.

...