Как оптимизировать запросы в базе данных - основы - PullRequest
6 голосов
/ 07 июля 2010

Кажется, что все вопросы по этой теме очень специфичны, и хотя я ценю конкретные примеры, меня интересуют основы оптимизации SQL.Мне очень удобно работать с SQL, и я имею опыт работы с аппаратным и низкоуровневым программным обеспечением.

Мне нужны инструменты и материальное программное обеспечение, и метод для просмотра баз данных mysql, на которые я смотрю в обычном режиме.основа и знать, в чем разница между порядками операторов объединения и где операторов.

Я хочу знать, почему индекс помогает, например, почему именно.Я хочу знать, что происходит по-другому, и я хочу знать, как я могу на самом деле смотреть на происходящее.Мне не нужен инструмент, который будет разбивать каждый шаг моего SQL, я просто хочу иметь возможность возиться, и если кто-то не может сказать мне, какой столбец индексировать, я смогу получить лист бумаги ив течение некоторого периода времени сможете найти ответы.

Базы данных сложны, но они НЕ ТАК сложны, и должен быть какой-то замечательный материал для изучения основ, чтобы вы знали, какчтобы найти ответы на проблемы с оптимизацией, с которыми вы сталкиваетесь, даже если бы вы могли найти точный ответ на форуме.

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

Ответы [ 5 ]

7 голосов
/ 07 июля 2010

Допустим, вы ищете друга в другом городе.Одним из способов было бы пойти от двери к двери и спросить, является ли это дом, который вы ищете.Другой способ - посмотреть на карту.

Индекс - это карта таблицы.Он может точно сказать движку БД, где находится то, что вы ищете.Таким образом, вы индексируете каждый столбец, который, по вашему мнению, придется искать, и опускаете столбцы, из которых вы просто читаете данные и никогда не ищете.* и о ORDER BY оптимизации .И если вы хотите увидеть, что именно происходит, вам нужен оператор EXPLAIN.

6 голосов
/ 07 июля 2010

Вы должны найти все условия где и каждое соединение ... при условии. Два работают одинаково.

Предположим, мы пишем

select name
from customer
where customerid=37;

Каким-то образом СУБД должна найти запись или записи с customerid = 37. Если индекса нет, единственный способ сделать это - прочитать каждую запись в таблице, сравнивая значение Customerid с 37. Даже когда он находит его, он не может знать, что есть только один, поэтому он должен искать др.

Если вы создаете индекс для customerid, у СУБД есть способы очень быстрого поиска в индексе. Это не последовательный поиск, а, в зависимости от базы данных, бинарный поиск или другой эффективный метод. Точно, как не важно, примите, что это намного быстрее, чем последовательный. Затем индекс переносит его непосредственно в соответствующую запись или записи. Кроме того, если вы укажете, что индекс является «уникальным», то база данных знает, что он может быть только один, поэтому не тратит время на поиски секунды. (А СУБД не позволит вам добавить секунду.)

Теперь рассмотрим этот запрос:

select name
from customer
where city='Albany' and state='NY';

Теперь у нас есть два условия. Если у вас есть индекс только для одного из этих полей, СУБД будет использовать этот индекс для поиска подмножества записей, а затем последовательно искать их. Например, если у вас есть индекс состояния, СУБД быстро найдет первую запись для Нью-Йорка, затем последовательно выполнит поиск в поиске city = 'Albany' и прекратит поиск, когда достигнет последней записи для Нью-Йорка.

Если у вас есть индекс, который включает оба поля, т. Е. «Создать индекс по клиенту (штат, город)», то СУБД может немедленно увеличить нужные записи.

Если у вас есть два отдельных индекса, по одному на каждое поле, СУБД будет иметь различные правила, которые она применяет, чтобы решить, какой индекс использовать. Опять же, как именно это делается, зависит от конкретной СУБД, которую вы используете, но в основном она пытается вести статистику по общему количеству записей, количеству различных значений и распределению значений. Затем он будет последовательно искать те записи, которые удовлетворяют другому условию. В этом случае СУБД, вероятно, заметит, что городов гораздо больше, чем штатов, поэтому с помощью индекса города можно быстро увеличить записи «Олбани». Затем он будет последовательно искать их, проверяя состояние каждого по отношению к «NY». Если у вас есть записи для Олбани, Калифорния, они будут пропущены.

Каждое соединение требует своего рода поиска.

Скажем, мы пишем

select customer.name
from transaction
join customer on transaction.customerid=customer.customerid
where transaction.transactiondate='2010-07-04' and customer.type='Q';

Теперь СУБД должна решить, какую таблицу читать в первую очередь, выбрать соответствующие записи и затем найти соответствующие записи в другой таблице.

Если бы у вас был индекс для транзакций.transactiondate и customer.customerid, наилучшим планом, вероятно, было бы найти все транзакции с этой датой, а затем для каждой из них найти клиента с совпадающим параметром customerid, а затем убедиться, что клиент имеет правильный тип.

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

Предположим, что вместо этого у вас есть только индексы для транзакции.customerid и customer.type. Тогда СУБД, скорее всего, будет использовать совершенно другой план. Вероятно, он просканирует таблицу клиентов для всех клиентов с правильным типом, а затем для каждой из них найдет все транзакции для этого клиента и последовательно найдет для них правильную дату.

Самый важный ключ к оптимизации - выяснить, какие индексы действительно помогут, и создать эти индексы. Дополнительные неиспользуемые индексы являются обременительными для базы данных, поскольку для их обслуживания требуется работа, а если они никогда не используются, это напрасная трата усилий.

Вы можете указать, какие индексы СУБД будет использовать для любого запроса с помощью команды EXPLAIN.Я использую это все время, чтобы определить, хорошо ли оптимизируются мои запросы или мне нужно создавать дополнительные индексы.(Прочитайте документацию по этой команде для объяснения ее вывода.)

Предостережение: Помните, что я сказал, что СУБД ведет статистику по количеству записей и количеству различных значений и так далее в каждой таблице.EXPLAIN может дать вам сегодня совершенно другой план, чем вчера, если данные изменились.Например, если у вас есть запрос, который объединяет две таблицы, и одна из этих таблиц очень мала, а другая большая, она будет смещена к чтению маленькой таблицы, а затем к поиску совпадающих записей в большой таблице.Добавление записей в таблицу может изменить размер, который больше, и, следовательно, приведет к тому, что СУБД изменит свой план.Таким образом, вы должны попытаться сделать EXPLAINS для базы данных с реалистичными данными.Работа с тестовой базой данных с 5 записями в каждой таблице имеет гораздо меньшее значение, чем работа с действующей базой данных.

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

2 голосов
/ 07 июля 2010

Не думайте об оптимизации баз данных.Подумайте об оптимизации запросов.

Как правило, вы оптимизируете один случай за счет других.Вам просто нужно решить, какие дела вас интересуют.

1 голос
/ 07 июля 2010

Я не знаю об инструментах MySql, но в MS SqlServer у вас есть инструмент, который показывает все операции, которые потребует запрос, и сколько времени обработки всего запроса займет.

ИспользованиеЭтот инструмент помог мне понять, как оптимизатор запросов оптимизирует запросы, гораздо больше, чем я думаю, что любая книга могла бы помочь, потому что то, что делает оптимизатор, часто нелегко понять.Изменяя запрос и, возможно, подчеркивая базу данных, я мог видеть, как каждое изменение влияло на план запроса.Есть определенные ключевые моменты при написании запросов, но мне кажется, что у вас уже есть представление о тех, так что оптимизация в вашем случае - это гораздо больше, чем какие-либо общие правила.После нескольких лет разработки базы данных я просмотрел несколько книг, специально посвященных оптимизации баз данных на SQL Server, и нашел очень мало полезной информации.

Быстрое приближение к Google придумало следующее: http://www.mysql.com/products/enterprise/query.html, что похоже на похожий инструмент.

Это, конечно, на уровне запросов, оптимизация на уровне базы данных - снова другой инструментно вы смотрите на такие параметры, как разделение базы данных на жесткие диски и т. д. По крайней мере, в SqlServer вы можете разделить таблицы на разные жесткие диски и даже дисковые пластины, и это может иметь большой эффект, поскольку диски иголовки привода могут работать параллельно.Другой способ состоит в том, как вы можете построить свои запросы так, чтобы база данных могла выполнять их в нескольких потоках и процессорах параллельно, но обе эти проблемы снова зависят от ядра базы данных и даже используемой вами версии.

1 голос
/ 07 июля 2010

«Меня особенно интересует, как индексы повлияют на объединения»

В качестве примера я возьму случай equijoin (ВЫБРАТЬ ИЗ A, B, ГДЕ Ax = By).

Если индексов вообще нет (что возможно в теории, но я думаю, что не в SQL), то в основном единственный способ вычислить объединение - это взять всю таблицу A и разбить ее на x, взять всю таблицу yи разделить его на y, затем сопоставить разделы и, наконец, для каждой пары совпадающих разделов вычислить результирующие строки.Это дорого (или даже невозможно из-за ограничений памяти) для всех, кроме самых маленьких таблиц.

Та же история, если существуют индексы A и / или B, но ни у одного из них нет x соответственно.y в качестве его первого атрибута.

Если существует индекс по x, но не по y (или наоборот), то открывается другая возможность: отсканировать таблицу B, для каждого значения выбора строки y, найти это значениев индексе и извлеките соответствующие строки A, чтобы вычислить соединение.Обратите внимание, что это все равно не принесет вам большой пользы, если не будут применены другие дополнительные ограничения (И z = ...) - за исключением случая, когда между значениями x и y мало совпадений.

Если упорядоченные индексы(индексы на основе хеш-функции не упорядочены) существуют как для x, так и для y, затем открывается третья возможность: выполнить соответствующее сканирование самих индексов (сами индексы, вероятно, будут меньше самих таблиц, поэтому сканирует сам индексзаймет меньше времени), и для соответствующих значений x / y вычислите объединение соответствующих строк.

Это базовая линия.Вариации возникают для соединений по x> y и т. Д.

...