Двоичный запрос медленнее, чем текстовый запрос + преобразование с помощью Postgresql?

Искал все подряд и так и не смог найти однозначного ответа. Я только начинаю создавать архитектуру приложения, и мы решили использовать Postgresql для нашей базы данных и C для сервера. Однако некоторые начальные тесты показывают некоторую сбивающую с толку цифру. Кажется, что доступ к базе данных через текстовые строки - самый быстрый метод, который мне кажется нелогичным. Конечно, база данных хранит целые числа и числа с плавающей запятой внутри как двоичные и должна преобразовывать их для представления в виде текста, который затем мне нужно преобразовать обратно в двоичный файл, чтобы использовать. Кажется, более быстрым путем было бы просто оставить все как двоичное, но на сегодняшний день я не могу получить двоичный доступ, чтобы продемонстрировать это преимущество.

Вот простой тестовый пример, который я построил, чтобы показать, что я вижу (схема + код)

http://pastebin.com/1AhB8avx

И я вижу такие моменты времени:

Начало итерации 0 ... Итерация 0: получено 50000 двоичных записей через PQparamExec за 35 секунд Итерация 0: получено 50000 двоичных записей через PQexecf за 34 секунды Итерация 0: получено 50000 текстовых записей через PQexec за 25 секунд

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

Это соответствует твоему опыту, или я просто где-то дурак?

Спасибо!


person Teeleton    schedule 11.12.2012    source источник
comment
Я быстро взглянул на ваш код, и похоже, что вы выполняете построчную обработку; эффективно вы тестируете свою сеть. Каждая извлекаемая вами запись выполняет одно обращение к базе данных (2 * 1..10 мс + задержка). Сама обработка - ничто по сравнению с этими накладными расходами ввода-вывода. (2 системных вызова + 2 * сетевых ввода-вывода на строку) Для сравнения: один запрос может легко выдать набор результатов из 100К записей в секунду. За одну поездку туда и обратно.   -  person wildplasser    schedule 11.12.2012
comment
На самом деле это всего лишь функция простого тестового примера. Фактическое приложение объединяет несколько таблиц и возвращает десятки строк, но результаты те же. Кроме того, база данных является локальной для сервера и обменивается данными через локальный сокет UNIX (а не через TCP-сокет). Кроме того, для всех намерений и целей любые накладные расходы должны быть идентичными для всех трех случаев, поскольку все они следуют по одному и тому же пути в базе данных. Единственное, что меняется, - это метод API для возврата данных.   -  person Teeleton    schedule 11.12.2012


Ответы (1)


Кажется, для этого нет причин, и на самом деле, когда вы запускаете ваш код на моем рабочем столе ubuntu, я не вижу такой разницы:

Starting iteration 0...
Iteration    0: fetched 50000 binary records via PQparamExec in 13 seconds
Iteration    0: fetched 50000 binary records via PQexecf in 13 seconds
Iteration    0: fetched 50000 text records via PQexec in 12 seconds

Starting iteration 1...
Iteration    1: fetched 50000 binary records via PQparamExec in 13 seconds
Iteration    1: fetched 50000 binary records via PQexecf in 14 seconds
Iteration    1: fetched 50000 text records via PQexec in 12 seconds

Starting iteration 2...
Iteration    2: fetched 50000 binary records via PQparamExec in 12 seconds
Iteration    2: fetched 50000 binary records via PQexecf in 13 seconds
Iteration    2: fetched 50000 text records via PQexec in 11 seconds

Starting iteration 3...
Iteration    3: fetched 50000 binary records via PQparamExec in 12 seconds
Iteration    3: fetched 50000 binary records via PQexecf in 12 seconds
Iteration    3: fetched 50000 text records via PQexec in 12 seconds

Starting iteration 4...
Iteration    4: fetched 50000 binary records via PQparamExec in 13 seconds
Iteration    4: fetched 50000 binary records via PQexecf in 12 seconds
Iteration    4: fetched 50000 text records via PQexec in 12 seconds

Обратите внимание: поскольку код дважды вызывает time() для измерения прошедшего времени, его точность составляет 2 секунды, что в данном контексте немного выше. Вместо этого вам следует рассмотреть gettimeofday(), а еще лучше clock_gettime() на CLOCK_PROCESS_CPUTIME_ID.

person Daniel Vérité    schedule 12.12.2012
comment
Интересно ... В моей системе разница достаточно выражена (и достаточно вариативна), поэтому попытки измерить до миллисекунды казались излишними. Даже в вашем выводе текстовые запросы неизменно являются самыми быстрыми из трех, даже если маржа значительно меньше. Возможно, мне нужно посмотреть конфигурацию моей сборки для postgresql. - person Teeleton; 12.12.2012