Postgresql: запросы в 10 раз медленнее в другом клиенте

Глядя на журнал сервера postgres, я вижу, что точно такой же запрос на том же сервере postgres выполняется намного дольше (примерно в 10 раз дольше) при вызове из клиента Linux или из клиента Windows.

Запросы исходят от приложения Django, работающего на компьютере с Linux с 4 ГБ ОЗУ и на компьютере с Windows с 8 ГБ ОЗУ. Обе среды pyhon имеют библиотеку psycopg2 версии 2.4.4 для отправки запросов на один и тот же сервер postgres.

Ниже приведены логи сервера postgres.

Запрос Windows (со временем):

2013-06-11 12:12:19 EEST [unknown] 10.1.3.152(56895) mferreiraLOG:  duration: 3207.195 ms  statement: SELECT "autotests_tracerperformance"."id", "autotests_tracerperformance"."date", "autotests_tracerperformance"."video_id", "autotests_tracerperformance"."revision_id", "autotests_tracerperformance"."computer_id", "autotests_tracerperformance"."probe", "autotests_tracerperformance"."time_tostart", "autotests_tracerperformance"."hang_atstart", "autotests_tracerperformance"."time_tohang", "autotests_tracerperformance"."hang", "autotests_tracerperformance"."crash", "autotests_tracerperformance"."stacktrace", "autotests_tracerperformance"."framemax", "autotests_tracerperformance"."maxtime", "autotests_tracerperformance"."avgtime" FROM "autotests_tracerperformance" INNER JOIN "revisions" ON ("autotests_tracerperformance"."revision_id" = "revisions"."id") WHERE ("autotests_tracerperformance"."computer_id" = 61  AND "revisions"."repo" = 'Trunk' )

Запрос Linux (намного дольше):

2013-06-11 12:12:56 EEST [unknown] 10.1.3.154(35325) mferreiraLOG:  duration: 22191.773 ms  statement: SELECT "autotests_tracerperformance"."id", "autotests_tracerperformance"."date", "autotests_tracerperformance"."video_id", "autotests_tracerperformance"."revision_id", "autotests_tracerperformance"."computer_id", "autotests_tracerperformance"."probe", "autotests_tracerperformance"."time_tostart", "autotests_tracerperformance"."hang_atstart", "autotests_tracerperformance"."time_tohang", "autotests_tracerperformance"."hang", "autotests_tracerperformance"."crash", "autotests_tracerperformance"."stacktrace", "autotests_tracerperformance"."framemax", "autotests_tracerperformance"."maxtime", "autotests_tracerperformance"."avgtime" FROM "autotests_tracerperformance" INNER JOIN "revisions" ON ("autotests_tracerperformance"."revision_id" = "revisions"."id") WHERE ("autotests_tracerperformance"."computer_id" = 61  AND "revisions"."repo" = 'Trunk' )

выполнение прямо из psql (самое быстрое):

2013-06-11 12:19:06 EEST psql [local] mferreiraLOG:  duration: 1332.902 ms  statement: SELECT "autotests_tracerperformance"."id", "autotests_tracerperformance"."date", "autotests_tracerperformance"."video_id", "autotests_tracerperformance"."revision_id", "autotests_tracerperformance"."computer_id", "autotests_tracerperformance"."probe", "autotests_tracerperformance"."time_tostart", "autotests_tracerperformance"."hang_atstart", "autotests_tracerperformance"."time_tohang", "autotests_tracerperformance"."hang", "autotests_tracerperformance"."crash", "autotests_tracerperformance"."stacktrace", "autotests_tracerperformance"."framemax", "autotests_tracerperformance"."maxtime", "autotests_tracerperformance"."avgtime" FROM "autotests_tracerperformance" INNER JOIN "revisions" ON ("autotests_tracerperformance"."revision_id" = "revisions"."id") WHERE ("autotests_tracerperformance"."computer_id" = 61  AND "revisions"."repo" = 'Trunk' );

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

Почему такая большая разница во времени между клиентами для этого запроса?

Примечание. Время передачи не имеет значения, так как все машины находятся в одной интрасети. Кроме того, более медленное время наблюдается, когда клиентский запрос поступает с той же машины Linux, на которой работает сервер postgresql.

Примечание 2. Psycopg2 устанавливался по-разному в Windows и Linux. В то время как в Windows я установил его из предварительно упакованного двоичного файла, в Linux я запустил «pip install psycopg2», который опирается на установку postgresql, доступную в системе. Может ли это привести к различным значениям параметров, влияющих на производительность на стороне клиента (например, параметр work_mem)?


person mpaf    schedule 11.06.2013    source источник
comment
Просто выстрел в темноте: может быть, это проблема внутреннего кэширования PostgreSQL? Вы пытались отправить оператор SELECT несколько раз из Linux, а также несколько раз из Windows? Я бы предположил, что тогда среднее время должно быть таким же.   -  person mawimawi    schedule 11.06.2013
comment
to mawimawi: Нет, эти времена постоянны, я начал отлаживать это, так как мое производственное приложение django было намного медленнее, чем на машине разработки (Windows). Время одинаковое, если вы запускаете несколько раз.   -  person mpaf    schedule 11.06.2013
comment
Это может быть связано с лагами сети. Особенно, если вы передаете большие объемы данных с одного сервера на другой. Зарегистрируйте запрос на уровне сервера, чтобы увидеть, сколько времени фактически тратится на Postgres. О, это также может быть разница во времени выполнения в python, например. создание объектов и т. д.   -  person Denis de Bernardy    schedule 11.06.2013
comment
Деннису: не совсем так, я протестировал запуск приложения django на той же машине, где находится сервер postgresql — это требует в 10 раз больше, чем от приложения django, работающего на другом компьютере с клиентом Windows. Кажется, это связано с конфигурацией клиента. Все серверы являются частью одной и той же локальной интрасети, это не должно иметь большого значения - и я думаю, что журнал postgresql показывает время работы на сервере postgres и не принимает во внимание передачу данных (?)   -  person mpaf    schedule 11.06.2013
comment
Я согласен с Денисом, это похоже на проблему с сетью - или проблему с сетевой картой станции Linux.   -  person Pavel Stehule    schedule 11.06.2013
comment
Я тестировал на двух разных станциях Linux - время одинаковое. Я все больше и больше думаю, что это проблема конфигурации psycopg2, которая отличается в установках Linux от установки Windows.   -  person mpaf    schedule 11.06.2013
comment
@mpaf: я все еще подозреваю проблемы с сетью. Есть ли шансы, что вы сможете запустить тест, чтобы увидеть, насколько дольше или короче ваши клиентские машины будут передавать файл, эквивалентный размеру вашего набора данных, хранящегося на вашем сервере?   -  person Denis de Bernardy    schedule 11.06.2013
comment
Причина, по которой я спрашиваю, - это разница во времени между psql и окном Windows. В последнем случае сеть, очевидно, вносит задержку более 1 тыс. мс...   -  person Denis de Bernardy    schedule 11.06.2013
comment
@Dennis: Да, это может объяснить разницу между psql и удаленным клиентом (Windows или Linux). Однако это не объясняет разницу между удаленным клиентом Windows и удаленным клиентом Linux, они сидят бок о бок, подключены к одному и тому же концентратору - И запуск «удаленного» клиента на том же компьютере, что и сервер postgres, дает то же самое. Разница во времени.   -  person mpaf    schedule 11.06.2013


Ответы (1)


Вы можете проверить, использует ли медленный клиент SSL-шифрование или нет. Это происходит по умолчанию, когда он настроен на сервере, а клиент скомпилирован с поддержкой SSL.

Для запросов, которые извлекают большие объемы данных, разница во времени значительна. Кроме того, в некоторых дистрибутивах Linux, таких как Debian/Ubuntu, SSL включен по умолчанию, даже для TCP-соединений через localhost.

В качестве примера, вот разница во времени для запроса, извлекающего 1,5 млн строк общим весом 64 Мб с теплым кешем.

Без шифрования:

$ psql "host=localhost dbname=mlists sslmode=disable"
Password: 
psql (9.1.7, server 9.1.9)
Type "help" for help.

mlists=> \timing
Timing is on.
mlists=> \o /dev/null
mlists=> select subject from mail;
Time: 1672.258 ms

С шифрованием:

$ psql "host=localhost dbname=mlists"
Password: 
psql (9.1.7, server 9.1.9)
SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256)
Type "help" for help.

mlists=> \o /dev/null
mlists=> \timing
Timing is on.
mlists=> select subject from mail;
Time: 7017.935 ms

Чтобы отключить его глобально, можно установить SSL=off в postgresql.conf.

Чтобы отключить его для определенных диапазонов клиентских адресов, добавьте записи в pg_hba.conf с hostnossl в первом поле перед более общими записями host.

Чтобы отключить его на стороне клиента, это зависит от того, как драйвер предоставляет параметр соединения sslmode. Если это не так, можно использовать переменную окружения PGSSLMODE, если драйвер реализован поверх libpq.

Что касается подключений через доменные сокеты Unix (local), то SSL для них никогда не используется.

person Daniel Vérité    schedule 11.06.2013
comment
Отличный ответ! Я проверил, и вы были правы, SSL влиял на производительность. Как для Windows, так и для Linux на самом деле, когда я отключил SSL в postgresql.conf, время Windows сократилось с 3 с до 1,7 с, а время Linux с 22 с до 1,5 с! Итак, кажется, что оба проходили через SSL, но Linux больше пострадал от этого? Большое спасибо за ответ, хорошее понимание. - person mpaf; 12.06.2013
comment
@mpaf: рад, что это помогает. Что касается Linux, который больше пострадал, это трудно объяснить без дополнительных исследований. Возможно, в Linux выбирается более надежный шифр, но это всего лишь предположение. - person Daniel Vérité; 12.06.2013