Diferença de desempenho entre MySQL e PostgreSQL para o mesmo esquema / consultas [fechado]

20

Sou um DBA iniciante e tenho experiência no Microsoft SQL Server, mas quero pular para o FLOSS.

Estou iniciando uma empresa e desenvolvemos um aplicativo (PHP) com um back-end do Postgres, e também fizemos alguns testes comparando com o MySQL. Observamos que o MySQL é duas vezes mais rápido que o PostgreSQL.

Fiz um teste de desempenho tangível:

  • Mesmas colunas na tabela com tipos de dados de coluna equivalentes.
  • Mesmo número de linhas.
  • Mesmos índices em ambos (chave primária incluída).
  • A carga da CPU está ociosa e a máquina do Postgres é significativamente melhor.
  • E a mesma consulta (obviamente).

O que estou fazendo errado?

PS: Eu li muitos "howtos" sobre ajuste de desempenho para mecanismos de banco de dados.
PS (2): Estamos usando o InnoDB (um arquivo por tabela) no banco de dados MySQL.


Oi Mat!

Fiz as três consultas comuns de seleção (e as mais difíceis).

A questão sobre disco, certamente não é a mesma; No Postgres, é um SSD (quase três vezes mais rápido).

Dados de cache do 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                    |
+------------------------------+----------------------+

Não sei como ver isso no PostgreSQL.

Desde já, obrigado.

Javier Valencia
fonte
Desculpem o meu inglês
Javier Valencia
(Seu inglês está bom.) Você carregou testes ou apenas consultas individuais? Você poderia mostrar as configurações do banco de dados que usou (especialmente itens como tamanhos de cache)? (Mesmos discos em ambos os casos, eu presumo?)
Mat
11
Você pode postar a consulta e o plano de execução do Postgres usando explain analyze. Para torná-lo mais fácil de ler, você pode enviar o plano para explain.depesz.com
a_horse_with_no_name
11
Se o Postgres estiver rodando em um SSD, você certamente precisará ajustarpostgresql.conf
a_horse_with_no_name
11
@JavierValencia: se você conseguiu resolver o problema, adicione uma resposta descrevendo o que você fez para que outras pessoas possam aprender com isso. Você também pode aceitar sua própria resposta para marcar esta pergunta como resolvida
a_horse_with_no_name

Respostas:

41

MySQL e PostgreSQL são bastante diferentes em termos de desempenho. As tabelas InnoDB e PostgreSQL são otimizadas para diferentes tipos de consultas. Entender essas diferenças é importante para entender como obter um bom desempenho.

Como exemplo, vejamos a diferença mais óbvia.

Estrutura da tabela do PostgreSQL x MySQL / InnoDB e o que isso significa para desempenho

Em geral, em cargas de trabalho complexas, o PostgreSQL será mais rápido, mas em pesquisas simples de chave primária, o MySQL com InnoDB será mais rápido.

As tabelas do PostgreSQL são tabelas de heap. Não há opção para criar uma tabela que não seja uma tabela de heap. O clustercomando simplesmente reescreve a pilha ordenada por um índice especificado. Os índices fornecem locais de heap para tuplas com vários valores. Os índices não podem ser percorridos em ordem física, apenas ordem lógica, para que eles tenham muitas E / S aleatórias de disco durante a leitura de uma tabela em sequência, geralmente significa muita E / S de disco seqüencial, pois é possível ler uma tabela em ordem física. A E / S de disco seqüencial utiliza o cache de leitura antecipada e alguma outra otimização no nível do SO.

O que isso significa é que, se você precisar de uma parte significativa dos registros ou de algumas páginas, geralmente é mais rápido ler as páginas do disco. Por outro lado, uma pesquisa de chave primária para uma tabela exige que você acerte o índice, procure o local no arquivo, depois acerte a tabela de heap e puxe o registro. Isso significa várias partes de E / S de disco aleatório.

O InnoDB usa uma abordagem diferente. Com o InnoDB, a tabela é um índice de árvore b com os dados reais na carga útil do índice. Isso significa que uma pesquisa de chave primária já consegue extrair os dados da página folha e, portanto, menos E / S de disco aleatória é necessária para isso. Ao mesmo tempo, uma varredura de índice requer a passagem de dois índices em vez de um, o que significa que o uso de qualquer índice que não seja a chave primária acaba sendo mais lento e as varreduras seqüenciais ainda mais lentas.

Obtendo diagnósticos no PostgreSQL

Eu acho que você deseja usar algo como:

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

Isso fornecerá o plano de consulta, estimativas iniciais, horários reais, uso de buffer e muito mais.

Chris Travers
fonte
4
+1 para EXPLAIN (analise, buffers, verbose) #
karmakaze
@ChrisTravers obrigado por uma ótima resposta! Você disse: "... as varreduras seqüenciais (do InnoDB) são mais lentas". Você poderia explicar o que você quer dizer com varreduras seqüenciais nesse contexto?
VB_
obrigado. Vou modificar a resposta. As verificações "sequenciais" no InnoDB estão na ordem lógica do índice, para que você tenha mais E / S aleatória e não obtenha ajuda do cache de leitura antecipada.
Chris Travers
Obrigado pela resposta agradável. Para qualquer pessoa curiosa sobre o interno do postgres, eu recomendo este post: interdb.jp/pg/pgsql01.html Explique como o Postgres armazena dados como tabela de heap.
hqt 03/02