InterBase: тормозология и глюконавтика
Страница 12. Сортировки


Сортировки

И так, индексы - индексами, но рано или поздно (обычно - раньше, чем кажется) interbase вынужден что-то сортитьвать "вручную", то есть трактуя записи, как изначально неупорядоченные. Для этого он начинает выделять, пока возможно, память. Но памяти рано или поздно не хватает. И тогда создаются временные файлы в каталоге \TEMP или /tmp. Факт появления этих файлов, их размер и характер роста наряду с планами так же может много сказать о "тяжести" запроса.

Обычно, при наличии существенных объёмов оперативной памяти, interbase удаётся всё отсортировать буквально за один проход. Судя по всему (и в соответствии с тем, что известно из литературы) он ведёт себя так: по мере поступления (вычитывания или вычисления) записей они сортируются в памяти. Когда память, отведённая под запрос, исчерпывается, отсортированное множество сбрасывается во временный файл, после чего память вновь начинает заполняться сначала. Если повезёт, то записи кончатся до заполнения памяти и временный файл не потребуется.

Когда файл сформирован, он состоит из нескольких отсортированных участков, позиции которых заблаговременно сохранены, видимо в памяти. interbase начинает вычитывать отсортированные участки и выполнять в памяти слияние, похожее на слияние таблиц. Это тем более легко, что отсортированность участков уже обеспечена. Как правило, участков достаточно мало и слияние удаётся сделать за один проход по временному файлу. По крайней мере мне не встречались случаи, чтобы на одну сортировку создавалось несколько файлов. Не заметить перегенерацию стомегабайтного файла я не мог.

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

Откуда берутся сортировки? Во-первых, конечно же, из order by. В ряде случаев это упорядочение можно выполнить по индексу, но часто оказывается, что лучше по другим индексам отфильтровать ненужные записи, а потом уж "вручную" отсортировать оставшееся множество. Кроме того, interbase не поддерживает индексирование по вычисляемым полям, так что сортировать по выражению можно только одним способом.

Во-вторых, group by. На самом деле это то же самое упорядочение, просто с чуть-чуть ослабленными условиями. В частности, для такого упорядочения тоже можно воспользоваться индексом в плане (как обычно, если это не конфликтует с условиями соединения, фильтрации, и того же упорядочения).

Вот что действительно проблематично заставить работать по индексам, так это having. К счастью, эти условия обычно обрабатывают единичные записи, образовавшиеся после группировки. То есть тормоза образуются главным образом в group by, а не в having. Если, конечно, не написать кривой подзапрос.

В-третьих, источник сортировки - sort merge. Не самый эффективный, но часто удовлетворительно эффективный способ соединения. Пара таблиц (возможно, образовавшихся в результате других частей запроса) сортируется по полям, на котоыре наложено условие соединения. После чего по результатам сортировки делается проход, во время которого собранные данные отправляются клиенту или (в совсем тяжёлом случае) на вход другогозапроса, после чего временные файлы уничтожаются. Мне приходилось видеть план запроса, сгенерированный interbase, в котором одна таблица фактически сортировалась трижды: два раза - чтобы соединить её с другими таблицами (сначала с одной, затем по другому полю - с другой), а в третий - по полям в order by. Разумеется, это был повод для ручной оптимизации.

В-четвёртых, сортировка делается при создании индексов. То есть create index по объёмистому множеству полей тоже может породить временный файл. Это касается любого, прямого или косвенного их создания. В частности, индексы создаются на заключительной стадии восстановления БД из бэкапа, при создании ссылочных и ключевых ограничений целостности. Последние, если их создавать вместе с таблицей, временных файлов не потребуют, так как таблица пока пуста и сортировать ещё нечего.

В-шестых, похоже, что через сортировку в interbase делается distinct.

 
« Предыдущая статья