Разница в производительности между MySQL и PostgreSQL для одной и той же схемы / запросов [закрыто]

20

Я начинающий администратор баз данных, и у меня есть опыт работы с Microsoft SQL Server, но я хочу перейти на FLOSS.

Я начинаю компанию, и мы разрабатываем приложение (PHP) с бэкэндом Postgres, а также провели несколько тестов по сравнению с MySQL. Мы видим, что MySQL в два раза быстрее PostgreSQL.

Я сделал ощутимый тест производительности:

  • Те же столбцы в таблице с эквивалентными типами данных столбцов.
  • Такое же количество строк.
  • Одинаковые индексы в обоих (первичный ключ включен).
  • Загрузка процессора простаивает, и машина Postgres значительно лучше.
  • И тот же запрос (очевидно).

Что я делаю неправильно?

PS: я прочитал много "Howtos" по настройке производительности для двигателей баз данных.
PS (2): Мы используем InnoDB (один файл на таблицу) в базе данных MySQL.


Привет, Мат!

Я выполнил три наиболее распространенных (и самых сложных) запроса.

Вопрос о диске, конечно, не тот; В Postgres это SSD (почти в три раза быстрее).

Данные кеша MySQL:

+------------------------------+----------------------+
| Variable_name                | Value                |
+------------------------------+----------------------+
| binlog_cache_size            | 32768                |
| have_query_cache             | YES                  |
| key_cache_age_threshold      | 300                  |
| key_cache_block_size         | 1024                 |
| key_cache_division_limit     | 100                  |
| max_binlog_cache_size        | 18446744073709547520 |
| query_cache_limit            | 1048576              |
| query_cache_min_res_unit     | 4096                 |
| query_cache_size             | 16777216             |
| query_cache_type             | ON                   |
| query_cache_wlock_invalidate | OFF                  |
| table_definition_cache       | 256                  |
| table_open_cache             | 64                   |
| thread_cache_size            | 8                    |
+------------------------------+----------------------+

Я не знаю, как просмотреть это в PostgreSQL.

Заранее спасибо.

Хавьер Валенсия
источник
Извините за мой английский
Хавьер Валенсия
(Ваш английский в порядке.) Вы делали нагрузочные тесты или только отдельные запросы? Не могли бы вы показать настройки базы данных, которые вы использовали (особенно такие вещи, как размеры кэша)? (Те же диски в обоих случаях я полагаю?)
Mat
1
Можете ли вы опубликовать запрос и план выполнения Postgres, используя explain analyze. Чтобы было удобнее читать, вы можете загрузить план для объяснения.depesz.com
a_horse_with_no_name
1
Если Postgres работает на SSD, вам почти наверняка придется настраиватьсяpostgresql.conf
a_horse_with_no_name
1
@JavierValencia: если вам удалось решить проблему, пожалуйста, добавьте ответ с описанием того, что вы сделали, чтобы другие могли извлечь из этого урок. Вы также можете принять собственный ответ, чтобы пометить этот вопрос как решенный
a_horse_with_no_name

Ответы:

41

MySQL и PostgreSQL сильно отличаются по производительности. Таблицы InnoDB и PostgreSQL оптимизированы для разных видов запросов. Понимание этих различий важно для понимания того, как получить хорошую производительность от любого из них.

В качестве примера давайте рассмотрим наиболее очевидную разницу.

PostgreSQL против структуры таблиц MySQL / InnoDB и что это означает для производительности

В общем, при сложных рабочих нагрузках PostgreSQL будет быстрее, но при простом поиске первичного ключа MySQL с InnoDB будет быстрее.

Таблицы PostgreSQL - это таблицы кучи. Нет возможности построить таблицу, которая не является таблицей кучи. Команда clusterпросто переписывает кучу, упорядоченную по указанному индексу. Индексы затем обеспечивают места кучи для кортежей с различными значениями. Индексы нельзя просматривать в физическом порядке, только в логическом порядке, поэтому они имеют много случайных дисковых операций ввода-вывода, а последовательное чтение таблицы обычно означает много последовательных дисковых операций ввода-вывода, поскольку вы можете читать таблицу в физическом порядке. Последовательный дисковый ввод-вывод используется для кеширования с опережением чтения и некоторой другой оптимизации на уровне ОС.

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

InnoDB использует другой подход. С InnoDB таблица представляет собой индекс b-дерева с фактическими данными в полезной нагрузке индекса. Это означает, что поиск по первичному ключу уже используется для извлечения данных с конечной страницы, поэтому для этого требуется меньше случайных операций ввода-вывода с диска. В то же время сканирование индекса требует прохождения двух индексов вместо одного, что означает, что использование любого индекса, кроме первичного ключа, заканчивается медленнее, а последовательное сканирование все еще медленнее.

Получение диагнозов в PostgreSQL

Я думаю, что вы хотите использовать что-то вроде:

 EXPLAIN (analyse, buffers, verbose)
 [query];

Это даст вам план запроса, начальные оценки, фактическое время, использование буфера и многое другое.

Крис Траверс
источник
4
+1 для ОБЪЯСНИТЬ (анализ, буферы, многословно)
karmakaze
@ChrisTravers спасибо за отличный ответ! Вы сказали: «... (InnoDB) последовательное сканирование медленнее». Не могли бы вы объяснить, что вы подразумеваете под последовательным сканированием в этом контексте?
VB_
Благодарю. Я изменю ответ. «Последовательное» сканирование в InnoDB выполняется в индексно-логическом порядке, поэтому у вас больше случайных операций ввода-вывода и никакой помощи от кэширования с опережением чтения.
Крис Треверс
Спасибо за хороший ответ. Для тех, кто интересуется внутренним содержанием postgres, я рекомендую этот пост: interdb.jp/pg/pgsql01.html Объясните, как Postgres хранит данные в виде таблицы кучи.
HQT