awk vs sql: предварительные результаты

From
Valentin Davydov (2:5020/400)
To
All
Date
2006-11-30T13:46:32Z
Area
RU.UNIX.BSD
From: Valentin Davydov <val@sqdp.trc-net.co.jp>

Напомню постановку задачи: есть более-менее однородная таблица, в строках
которой присутствуют, помимо прочих, поля "клиент" и "количество". Требуется
для каждого клиента сосчитать полную сумму по всей таблице.

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

У меня имеется некая SQL-база с достаточно большой таблицей. Достаточно - 
это значит, что ни сама таблица, ни промежуточные данные, ни конечный
результат в память не помещаются, так что и sql, и awk находятся в одинаковых
условиях, производительность ограничена дисковыми операциями. Ибо в противном
случае (когда вся база влезает в ОЗУ) о тормозах и речи нет, нынешние
процессоры весьма быстры.

Sql сервер (конкретно sqlite3, но не думаю, что результат принципиально
изменится при использовании другого) для выполнения запроса выбрал следующую
стратегию: двигаясь по (упорядоченному, в качестве бонуса) индексу клиентов он
собирает все строчки, относящиеся к данному клиенту, выдаёт строку результата
и переходит к следующему клиенту. Таким образом, он обращается к каждой строке
таблицы ровно один раз, но в случайном порядке. И к каждой записи в индексе,
замечу, он обращается тоже по одному разу. Селект выполнился за 12 с небольшим
суток.

Затем был выполнен select * from table, и на полученный текстовый файл
(к слову сказать, занимающий примерно вдвое меньше места на диске, нежели
структурированный файл базы данных) натравлен awk '{a[$2]+=$7};
END{for(c in a) print c, a[c]}' | sort -k1. Поскольку awk вынужден 
рассматривать строки в том порядке, в котором они идут в таблице, ему
_каждый_ раз приходится обращаться к индексу (массиву a), достраивая его
по мере необходимости. Сейчас awk работает уже шестые сутки, и за это
время переварил только 25% исходного файла. Даже если предположить линейную
зависимость количества обработанных данных от времени (а она, скорее
всего, сильно сублинейна, ближе к корневой), то уже видно, что awk заметно
проигрывает на этой задаче sqlю.

Когда (и если - мало ли на какие ограничения он может наткнуться) awk
закончит свою работу, я, надеюсь, опубликую более подробные данные.

Вал. Дав.
--- 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