Re: awk vs sql: предварительные результаты
- From
- Valentin Davydov (2:5020/400)
- To
- Slawa Olhovchenkov
- Date
- 2006-11-30T17:09:36Z
- Area
- RU.UNIX.BSD
From: Valentin Davydov <val@sqdp.trc-net.co.jp>
> From: Slawa Olhovchenkov <Slawa.Olhovchenkov@f500.n5030.z2.fidonet.org>
> Date: Thu, 30 Nov 2006 14:21:06 +0300
>
> VD> Напомню постановку задачи: есть более-менее однородная таблица, в строках
> VD> которой присутствуют, помимо прочих, поля "клиент" и "количество".
> VD> Требуется для каждого клиента сосчитать полную сумму по всей таблице.
>
> VD> В эхе было высказано мнение о том, что awk на этой задаче порвёт любой
> VD> SQL-сервер. Я усомнился, поскольку правильно подготовленная таблица в
> VD> SQL-базе содержит весьма существенные хинты, а тупой awk вынужден идти
> VD> алгоритмически неэффективным путём. Для проверки решил поставить
> VD> эксперимент.
>
> VD> У меня имеется некая SQL-база с достаточно большой таблицей. Достаточно -
> VD> это значит, что ни сама таблица, ни промежуточные данные, ни конечный
> VD> результат в память не помещаются, так что и sql, и awk находятся в
> VD> одинаковых условиях, производительность ограничена дисковыми операциями.
> VD> Ибо в противном случае (когда вся база влезает в ОЗУ) о тормозах и речи
> VD> нет, нынешние процессоры весьма быстры.
>
> VD> Sql сервер (конкретно sqlite3, но не думаю, что результат принципиально
> VD> изменится при использовании другого) для выполнения запроса выбрал
> VD> следующую стратегию: двигаясь по (упорядоченному, в качестве бонуса)
> VD> индексу клиентов он собирает все строчки, относящиеся к данному клиенту,
> VD> выдаёт строку результата и переходит к следующему клиенту. Таким образом,
> VD> он обращается к каждой строке таблицы ровно один раз, но в случайном
> VD> порядке. И к каждой записи в индексе, замечу, он обращается тоже по одному
> VD> разу. Селект выполнился за 12 с небольшим суток.
>
> VD> Затем был выполнен select * from table, и на полученный текстовый файл
> VD> (к слову сказать, занимающий примерно вдвое меньше места на диске, нежели
> VD> структурированный файл базы данных) натравлен awk '{a[$2]+=$7};
> VD> END{for(c in a) print c, a[c]}' | sort -k1. Поскольку awk вынужден
> VD> рассматривать строки в том порядке, в котором они идут в таблице, ему
> VD> _каждый_ раз приходится обращаться к индексу (массиву a), достраивая его
> VD> по мере необходимости. Сейчас awk работает уже шестые сутки, и за это
> VD> время переварил только 25% исходного файла. Даже если предположить
> VD> линейную
> VD> зависимость количества обработанных данных от времени (а она, скорее
> VD> всего, сильно сублинейна, ближе к корневой), то уже видно, что awk заметно
> VD> проигрывает на этой задаче sqlю.
>
> VD> Когда (и если - мало ли на какие ограничения он может наткнуться) awk
> VD> закончит свою работу, я, надеюсь, опубликую более подробные данные.
>
>А программу на awk оптимизировать пробовал? Написать на нем сначала внешнюю
>ленточную сортировку, потом результать в один проход агрегировать.
Я, пока писал вышеотквоченное, ещё решил sort | awk попробовать. Только ведь
сортируй - не сортируй, всё равно промежуточные данные на диск должны лезть.
Правда, с sortом всё не так чисто: при том количестве промежуточных файлов
в $TMPDIR, которые он создаёт, ещё нормально работает dirhash. Но чтобы и
это проверить, надо не просто много данных, а экспоненциально много, а у
меня такого количества дисков и времени нету.
Вал. Дав.
--- ifmail v.2.15dev5.3
* Origin: Demos online service (2:5020/400)
SEEN-BY: 50/12 400/814 450/159 1024 461/43 132 640 469/999 4616/3 4625/8
SEEN-BY: 4641/444 5000/76 5000 5006/1 5007/1 5010/70 5011/13 5012/46 5015/28
SEEN-BY: 5019/26 31 5020/18 175 194 400 545 982 1057 1909 1922 2238 2395 2871
SEEN-BY: 5020/4441 5021/29 5025/3 5026/14 45 5027/12 5030/1080 1957 5034/10 13
SEEN-BY: 5035/3 38 5036/1 5045/7 5049/1 5051/15 5054/1 4 8 9 11 28 35 36 37 45
SEEN-BY: 5054/66 67 70 75 84 85 5059/9 5060/88 5061/15 5062/10 5063/3 5064/7
SEEN-BY: 5066/18 5075/5 5076/1 5077/70 5080/1003 5084/9 5085/13 5095/20
SEEN-BY: 5096/18 6001/10
PATH: 5020/400 545 5054/1 37