metaclass: (Default)
metaclass ([personal profile] metaclass) wrote2013-04-23 07:16 pm

Firebird, group by и временные файлы

Покопался в исходниках Firebird (2.5.2) на тему размеров временных файлов.
В итоге, там картина примерно такая:
* Запрос с условием и group by, входной датасет - десятки миллионов записей, результатирующий датасет - 150000 записей, размер записи порядка 150 байт (varchar расширены до максимального размера).
* Для выполнения запроса, подпадающие под условие записи (десятки миллионов) пишутся в сортировщик, затем досортировываются и выгребаются из него в правильном порядке с вычислением аггрегатов.
* Сортировщик реализован поверх временного хранилища данных, которое в свою очередь представляет последовательность блоков размером 1 мб, поначалу находящихся в памяти, а по мере превышения порога (8 МБ по умолчанию для классик-сервера) - записываемых во временные файлы. По виду это все крайне напоминает самодельную реализацию pagefile.
* Временные файлы расширяются кусками по 64 мб, с записью 262144 байтных буферов с нулями в эти куски.

Что здесь очень мне не нравится - это то, что обмен с временными файлами в принципе не выровнен по границам блоков диска, а является кратным размеру записи. Вот, например, из отладочного лога TempSpace::write: 2898976500 1048500

Второе - по-моему, конкретно для данного случая положить готовый результат group by в памяти в виде какого-нибудь дерева поиска и считать аггрегаты на ходу в него было бы гораздо эффективнее, чем долбится в i/o. Фактически мы при запросе читаем всю таблицу, пишем часть прочитанного в временный файл, потом сортируем, потом читаем обратно.
Но, возможно, нету эффективных способов отличить небольшой размер результата от большого размера, который эффективнее делать через сортировку.

[identity profile] nicka-startcev.livejournal.com 2013-04-23 04:22 pm (UTC)(link)
ммап() и 64 бита заметно упростят эту проблему, по идее.

[identity profile] metaclass.livejournal.com 2013-04-23 04:26 pm (UTC)(link)
Там, в целом, было бы достаточно сунуть 16 гиг памяти, воткнуть супер-сервер и сделать лимит памяти 4 гига для сортировщика.
Проблема в том, что классик-сервер создает по процессу на каждого юзера и если туда поставить хотя бы немного осмысленный лимит памяти - на серваке после 2-3 юзеров кончится память :)

[identity profile] denisioru.livejournal.com 2013-04-23 04:37 pm (UTC)(link)
Костыльно-велосипедная технология :))

[identity profile] nicka-startcev.livejournal.com 2013-04-23 04:52 pm (UTC)(link)
замапил, всосал, отсортировал, размапил. Память вернулась.
при этом вопрос о "как кэшировать/аллоцировать замапленое" решает ОС и, по идее, решает кошерно.

[identity profile] gds.livejournal.com 2013-04-23 04:50 pm (UTC)(link)
мене рассказывали, что mmap будет похуже, чем пряморукая работа с файлами.

[identity profile] nicka-startcev.livejournal.com 2013-04-23 04:53 pm (UTC)(link)
я плотник. Возможно, это сильно осезависимо, настройкозависимо, итп.

[identity profile] kiryl.livejournal.com 2013-04-23 04:58 pm (UTC)(link)
Все кому *действительно* нужно быстро, пользуют O_DIRECT.

[identity profile] gds.livejournal.com 2013-04-23 05:33 pm (UTC)(link)
ваистену так, ибо.