|
Программирование >> Программный интерфейс приложений
в этом случае СУБД MySQL анализирует предложение where, пони-i [ает , что ни одна строка не удовлетворяет условию, и даже не запускает операцию выборки из таблицы Это можно увидеть в операторе explain, который запрашивает у СУБД MySQL информацию о том, каким образом будет выполняться запрос select без его реального выполнения. Для этого перед оператором select необходимо указать ключевое слово explain: EXPLAIN SELECT * FROM tbl name WHERE 1=0 Этот оператор возвратит: +------------------+ I Conraient I 4.------------------+ I Impossible WHERE +------------------+ Обычно explain возвращает больше информации, чем приведено в этом примере. Эта информация включает описание индексов, которые будут использованы для сканирования таблиц, типы используемых объединений, данные о количестве строк, которые будут просканированы в таблице. Как работает оптимизатор Оптимизатор запросов СУБД MySQL преследует несколько целей, но главная цель - применять индексы везде, где это возможно, и использовать наиболее строгий индекс для того, чтобы максимально минимизировать количество просматриваемых строк Это звучит тем более удивительно, что вашей основной задачей при задании оператора select является поиск строк, а не исключение их из рассмотрения Причина такой работы заключается в том, что чем быстрее оптимизатор исключает строки из рассмотрения, тем быстрее будут найдены строки, удовлетворяющие условию. Запросы будут обрабатываться быстрее, если более строгие тесты будут отработаны в первую очередь. Предположим, что наш запрос тестирует два проиндексированных столбца WHERE coll = одно значение AND со12 = другое значение Предположим также, что тест по столбцу coll дал 900 строк, а тест по столбцу со 12 дал 300 строк, а объединение дало 30 строк. Если протестировать сначала coll, необходимо просмотреть 900 строк, а затем найти из них 30 строк, которые будут совпадать со значениями из столбца со12. Это составляет 870 ошибочных тестов. Если проверку начать со столбца со12, предстоит проверить только 300 строк, чтобы найти 30, которые будут совпадать со столбцом coll. Это всего 270 ошибочных тестов. Очевидно, что второй вариант требует меньше вычислений и операций ввода/вывода. Кроме того, можно упростить работу оптимизатора, придерживаясь следующих правил. Сравнивайте столбцы, имеющие одинаковый тип. При сравнении проиндексированных столбцов следует сравнивать столбцы, имеющие одинаковые типы. Например, тип char (10) можно рассматривать как тип, аналогичный типам char (10) и varchar (10), но отличный от типов char (12) и varchar (12). Типы int И bigint тоже различаются. Использование столбцов одного и того же типа является требованием всех версий СУБД MySQL до версии 3.23. В противном случае индексы будут проигнорированы. Начиная с версии 3.23, этого правила придерживаться не обязательно, но использование в операциях сравнения идентичных столбцов по сравнению с использованием различных типов повысит производительность. Если столбцы, которые вы сравниваете, являются столбцами различного типа, их тип можно предварительно изменить с помощью оператора alter table. Старайтесь выбирать для сравнений независимые проиндексированные столбцы. Нельзя индексировать столбцы, которые используются в качестве параметра функции или операнда арифметического выражения. Это вынудит СУБД MySQL вычислять выражение для каждой строки таблицы. Иногда это неизбежно, но во многих случаях есть возможность переписать запрос, чтобы он обращался к проиндексированному столбцу непосредсвенно. Следующее предложение where продемонстрирует это. В первой строке оптимизатор упростит выражение 4/2 до 2, а затем использует индекс по столбцу ту со1 для того, чтобы быстро найти значения ту со1 меньще 2. Во втором выражении СУБД MySQL будет искать значение mycol для каждой строки, умноженной на 2, и затем сравнит результат с 4. Индекс не используется потому, что все значения в левой стороне выражения вычисляются; WHERE my col < 4 / 2 WHERE my col * 2 < 4 Рассмотрим другой пример. Предположим, что столбец datecol проиндексирован. При запуске такого запроса индекс не нужен: SELECT * FROM my tbl WHERE YEAR(date col) < 1990 Это выражение не сравнивает непосредственно проиндексированный столбец со значением 1990, оно сравнивает значение, полученное из столбца, и это значение вычисляется для каждого столбца. В результате индекс по столбцу datecol не используется. Как исправить эту ситуацию? Просто воспользоваться литеральной датой, и индекс date col заработает . WHERE date col < 1990-01-01 Но предположим, что у нас нет конкретной даты. Вместо определения конкретной даты может понадобиться определить записи, содержащие даты, которые лежат через определенное количество дней от текущей даты. Эти запросы можно написать тремя разными способами, которые никак нельзя назвать равноценными: WHERE TO DAYS(date col) - TO DAYS(CURRENT DATE) < cutoff WHERE TO DAYS{date col) < cutoff + TO DAYS(CURRENT DATE) WHERE date C01 < DATE ADD(CURRENT DATE, INTERVAL cutoff DAY) В первой строке индекс не используется потому, что значение to days (date col) ДЛЯ каждой строки вычисляется. Вторая строка лучше. Как cutoff, так и to days (Current date) являются константами, таким образом, правая сторона выражения может вычисляться оптимизатором до обработки запроса, а не один раз на строку. Но столбец date col упоминается здесь в качестве параметра функции, таким образом, индекс в этом случае не используется. Наконец, третья строка предоставляет возможность использовать индекс. Опять правая сторона выражения вычисляется один раз как константа до выполнения запроса, но на этот раз значение является календарной датой. Значение сравнивается непосредственно со значением столбца datecol, которое больше не надо преобразовывать в дни. В этом случае используются индексы. Не используйте образцы в начале шаблона LIKE. Иногда выборку задают следуюшим образом; WHERE со1 пагае LIKE %string% Это приемлемо в том случае, если целью поиска является строка string, которая может находиться в любом месте в проверяемой строке. Но не следует возводить такой метод в ранг обычного приема. Если в действительности производится выборка строки только тогда, когда подстрока находится в начале столбца, первый символ % можно опустить. Например, при поиске строк в столбце, содержащем фамилии, начинающиеся с Мае , нужно написать предложение where такого типа: WHERE last name LIKE Мас% Оптимизатор анализирует начальную литеральную часть образца, и в зависимости от этого, индекс будет использоваться или не использоваться, как если бы было задано выражение в форме, позволяющей использование индекса по столбцу last name; where last name >= Mac AND last name < Mad Это правило не распространяется на образцы, которые используются с оператором regexp. Помогайте оптимизатору производить более эффективную оценку эффективности индекса. По умолчанию при сравнении значений из проиндексированного столбца с константой оптимизатор предполагает, что ключевые значения располагаются по индексу равномерно. Оптимизатор произведет быструю проверку индекса на предмет того, сколько записей будет использоваться. Это поможет в определении возможности использования индекса для сравнения с константами. Оптимизатор можно снабдить более полной информацией, если задать опцию - -analyze утилиты inyisainch)
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |