Sobre o desempenho de bancos de dados de thread único versus multithread

58

H2 é um banco de dados único com uma boa reputação em relação ao desempenho. Outros bancos de dados são multiencadeados.

Minha pergunta é: quando um banco de dados multithread se torna mais interessante que um banco de dados single thread? Quantos usuários? Quantos processos? Qual é o gatilho? Alguém tem experiência para compartilhar?

Sumário

  • O gargalo usual é o acesso ao disco
  • Os SSDs são rápidos, mas frágeis (o procedimento de falha é obrigatório)
  • Uma consulta longa em um sistema de thread único bloqueará todas as outras
  • Configurar o sistema multi-threading pode ser complicado
  • Bancos de dados multithread são benéficos mesmo em sistemas de núcleo único
Jérôme Verstrynge
fonte
Thread significa "thread ou processo" para o propósito desta pergunta, tanto quanto eu posso dizer - por exemplo, o postgres não é multiencadeado, mas a pergunta não está tentando comparar (H2, postgres) com (Oracle, SQL Server etc.)
Jack Douglas

Respostas:

31

Aqui está a minha opinião:

Geralmente, o gargalo (ou a parte mais lenta) de um sistema de banco de dados é o disco. A CPU apenas dispara durante operações aritméticas, processamento ou qualquer outra tarefa que a CPU realiza. Com arquitetura adequada, o multithreading pode ajudar a compensar a carga de uma consulta na CPU, em vez de fazer leituras / gravações lentas no disco. Há casos em que é mais rápido calcular um valor usando os ciclos da CPU do que criar uma coluna computada (que foi salva anteriormente no disco) e ler essa coluna do disco.

Em alguns RDBMS, há um banco de dados temporário (tempdb) usado por todos os bancos de dados nessa instância para classificação, hash, variáveis ​​temporárias, etc ... A multithreading e a divisão desses arquivos tempdb podem ser usadas para melhorar a taxa de transferência do tempdb , melhorando assim o desempenho geral do servidor.

Usando multithreading (paralelismo), o conjunto de resultados de uma consulta pode ser dividido para ser processado nos diferentes núcleos do servidor, em vez de usar apenas um núcleo. Esse recurso nem sempre melhora o desempenho, mas há casos em que o faz e, portanto, o recurso está disponível.

Os threads disponíveis para o banco de dados são usados ​​para vários propósitos: leitura / gravação em disco, conexões do usuário, trabalhos em segundo plano, bloqueio / trava, E / S de rede, etc ... Dependendo da arquitetura do sistema operacional, os threads são alimentados preventivamente na CPU e são gerenciado usando esperas e filas. Se a CPU puder processar esses threads rapidamente, os tempos de espera serão baixos. Um banco de dados multiencadeado será mais rápido que um banco de dados único, pois em um banco de dados único haverá a sobrecarga de reciclar apenas um segmento, em vez de ter outros passos disponíveis.

A escalabilidade também se torna um problema, pois mais threads serão necessários para gerenciar e executar o sistema de banco de dados em escala.

StanleyJohns
fonte
Obrigado pela compreensão. Eu ouço pessoas elogiando unidades de estado sólido. Eu acho que investir neles é provavelmente a melhor coisa a se fazer depois de garantir que as consultas sejam bem escritas e o aplicativo seja razoavelmente paralelo.
Jérôme Verstrynge
@ Stan - Eu acho que multithreadednesse contexto significa algo diferente , ou seja, que todas as transações são serializadas como Lucas menciona em sua resposta.
Jack Douglas
@JVerstry ~ Não, na verdade não. Leia os pensamentos de Jeff Atwood sobre SSDs ... eles têm uma alta taxa de falhas. A melhor coisa a fazer é indexar corretamente os dados e ter consultas bem escritas.
jcolebrand
@jcolebrand Ok, ele parece defender-los para a velocidade apenas com um sistema de backup forte para quando eles falham
Jérôme Verstrynge
2
@Jverstry ~ Sim, e se você entender esse conceito e concordar com ele, não se importe em reconstruir todo o seu ambiente de produção (ou em esperar um failover automático para iniciar e depois em algum momento no futuro próximo) vá em frente, eles vão tornar as coisas mais rápidas ainda, sim.
jcolebrand
47

Se há algo que posso dizer sobre o MySQL é que o InnoDB, seu mecanismo de armazenamento transacional (compatível com ACID), é de fato multithread. No entanto, é tão multithread quanto VOCÊ CONFIGURA !!! Mesmo "pronto para uso", o InnoDB tem um ótimo desempenho em um único ambiente de CPU, devido às configurações padrão. Para tirar proveito dos recursos de multithreading do InnoDB, lembre-se de ativar várias opções.

innodb_thread_concurrency define o limite superior do número de threads simultâneos que o InnoDB pode manter aberto. O melhor número de rodada definido para isso é (2 X Número de CPUs) + Número de Discos. ATUALIZAÇÃO : Como aprendi em primeira mão com a conferência Percona NYC, você deve definir isso como 0 para alertar o InnoDB Storage Engine para encontrar o melhor número de threads para o ambiente em que está executando.

innodb_concurrency_tickets define o número de encadeamentos que podem ignorar a verificação de simultaneidade com impunidade. Depois que esse limite é atingido, a verificação de simultaneidade de encadeamento se torna a norma novamente.

innodb_commit_concurrency define o número de transações simultâneas que podem ser confirmadas. Como o padrão é 0, não definir isso permite que qualquer número de transações seja confirmado simultaneamente.

innodb_thread_sleep_delay define o número de milissegundos que um encadeamento do InnoDB pode estar inativo antes de entrar novamente na fila do InnoDB. O padrão é 10000 (10 s).

innodb_read_io_threads e innodb_write_io_threads (ambos desde o MySQL 5.1.38) alocam o número especificado de threads para leituras e gravações. O padrão é 4 e o máximo é 64.

innodb_replication_delay impõe o atraso do encadeamento em um escravo quando innodb_thread_concurrency for atingido.

innodb_read_ahead_threshold permite leituras lineares do número definido de extensões (64 páginas [página = 16K]) antes de mudar para leitura assíncrona.

O tempo me escaparia se eu nomeasse mais opções. Você pode ler sobre eles na documentação do MySQL .

A maioria das pessoas desconhece esses recursos e está bastante satisfeita com o InnoDB apenas realizando transações compatíveis com ACID. Se você ajustar alguma dessas opções, fá-lo por sua própria conta e risco.

Eu joguei com várias instâncias de buffer pool do MySQL 5.5 (162 GB em 9 instâncias de buffer pools) e tentei particionar os dados automaticamente na memória dessa maneira. Alguns especialistas dizem que isso deve oferecer 50% de melhoria no desempenho. O que consegui foi uma tonelada de bloqueio de threads que realmente fez o InnoDB rastrear. Eu mudei para 1 buffer (162GB) e tudo estava bem novamente no mundo. Acho que você precisa de especialistas da Percona à sua disposição para definir isso. Estarei na Conferência MySQL da Percona em Nova York amanhã e perguntarei sobre isso se a oportunidade se oferecer.

Em conclusão, o InnoDB se comporta bem agora em um servidor com várias CPUs, considerando suas configurações padrão para operações multithread. Ajustá-los exige muito cuidado, muita paciência, ótima documentação e ótimo café (ou Red Bull, Jolt, etc.).

Bom dia, boa noite e boa noite !!!

ATUALIZAÇÃO 27-05-2011 20:11

Voltei da conferência Percona MySQL em Nova York na quinta-feira. Que conferência. Aprendi bastante, mas recebi uma resposta sobre o InnoDB. Fui informado por Ronald Bradford que definir innodb_thread_concurrency como 0 permitirá ao InnoDB decidir o melhor curso de ação internamente com simultaneidade de thread. Vou experimentar isso ainda mais no MySQL 5.5.

UPDATE 2011-06-01 11:20

No que diz respeito a uma longa consulta, o InnoDB é compatível com ACID e funciona muito bem usando o MultiVersion Concurrency Control . As transações devem ser capazes de transportar níveis de isolamento (leituras repetíveis por padrão) que impedem que outras pessoas acessem dados.

Quanto aos sistemas com vários núcleos, o InnoDB percorreu um longo caminho. No passado, o InnoDB não apresentava bom desempenho em um ambiente multicore. Lembro-me de ter que executar várias instâncias mysql em um único servidor para obter os múltiplos núcleos para distribuir os vários processos mysqld pelas CPUs. Isso não é mais necessário, graças à Percona e, mais tarde, ao MySQL (eh, Oracle, dizendo que isso ainda me deixa louco), pois eles desenvolveram o InnoDB em um mecanismo de armazenamento mais maduro que pode acessar os núcleos com simplicidade sem muito ajuste. A instância atual do InnoDB hoje pode operar bem em um único servidor núcleo.

RolandoMySQLDBA
fonte
11

Assim que você tiver vários usuários ou processos simultâneos, ou mesmo um único processo com acesso a banco de dados multiencadeado, ter um banco de dados que suporte o encadeamento se tornará potencialmente interessante.

O H2 é seguro para threads, mas serializa todas as solicitações no banco de dados, o que pode se tornar um possível problema de desempenho em um cenário de carga pesada. Se esse é realmente o caso de um projeto específico, depende de uma combinação de seus requisitos de desempenho, do número de threads / usuários / processos que acessam o banco de dados, da frequência de consultas executadas por esses threads e do desempenho médio e do pior caso possível. consultas.

Por exemplo, se seus requisitos de desempenho tiverem uma resposta em um segundo, você não terá mais de 10 usuários simultâneos executando uma única consulta que leva 0,05 segundos para executar, um banco de dados de thread único ainda permitirá que você atinja esses objetivos (embora com vários threads) provavelmente já daria um aumento notável no desempenho). Dado o mesmo cenário com uma única consulta em potencial e com o pior desempenho de meio segundo, serializar o acesso ao banco de dados não permitirá mais que você atinja suas metas de desempenho.

Se você estiver usando H2 no seu projeto, recomendamos que você execute um criador de perfil na sua base de código em um cenário de carregamento (apenas inicie um número x de threads que atingem seu código simultaneamente usando algumas casos de uso típicos). Isso fornecerá métricas reais sobre o desempenho e gargalos na sua base de código, em vez de apenas teorizar. Se isso mostra suas solicitações gastando uma grande porcentagem de seu tempo apenas aguardando para acessar o banco de dados, é hora de mudar para um banco de dados encadeado.

Luke Hutteman
fonte
H2 serializa todas as solicitações - ou apenas DML?
Jack Douglas
8

Pelo que posso dizer, "single-threaded" é um pouco impróprio para H2. O ponto é que ela serializa todas as transações (isto é, faz uma de cada vez).

A questão crucial sobre se isso é "ok" ou não para o seu aplicativo não é "Quantos usuários?" ou até "Quantos processos?", mas "Quanto tempo minhas transações levarão?"

Se todas as suas transações forem de menos de um segundo, isso pode ser bom, se algumas levarem várias horas para serem concluídas, isso pode não ser bom, pois todas as outras transações pendentes aguardam a conclusão. A decisão sobre se isso é "bom" ou não dependerá de seus próprios requisitos de desempenho - ou seja, quanto tempo é uma espera aceitável para que meus usuários acessem o banco de dados com transações.

--EDITAR

Parece que o H2 realmente não serializa transações - apenas DML. Em outras palavras, muitas atualizações curtas em uma única transação longa não bloquearão outras atualizações . No entanto, a menos que você esteja usando o recurso MVCC experimental , o bloqueio de tabela significa que isso tem um efeito semelhante na prática. Há também um recurso experimental "multi_threaded", mas não pode ser usado ao mesmo tempo que o MVCC

Jack Douglas
fonte
5

Citando partes do site do PostgreSQL ... Observe que não tenho absolutamente nenhuma idéia dos méritos desses argumentos - eles simplesmente não se encaixam em um comentário.

Nas Perguntas frequentes do desenvolvedor ("Por que os threads não são usados ​​..."):

http://wiki.postgresql.org/wiki/Developer_FAQ#Why_don.27t_you_use_threads.2C_raw_devices.2C_async-I.2FO.2C_.3Cinsert_your_favorite_wizz-bang_feature_here.3E.3F

Atualmente, os encadeamentos não são usados ​​em vez de vários processos para back-end porque: (...)

  • Um erro em um back-end pode corromper outros back-end se forem threads em um único processo
  • As melhorias de velocidade usando threads são pequenas em comparação com o tempo restante de inicialização do back-end.
  • O compartilhamento de mapeamentos executáveis ​​somente leitura e o uso de shared_buffers significa que processos, como threads, são muito eficientes na memória
  • A criação e destruição regulares de processos ajudam a proteger contra a fragmentação da memória, que pode ser difícil de gerenciar em processos de longa execução

Na lista Todo ("Recursos que não queremos"):

http://wiki.postgresql.org/wiki/Todo#Features_We_Do_Not_Want

Todos os back-ends em execução como threads em um único processo (não desejado)

Isso elimina a proteção do processo que obtemos da configuração atual. A criação de encadeamentos geralmente é a mesma sobrecarga que a criação de processos em sistemas modernos, portanto, parece imprudente usar um modelo encadeado puro, e o MySQL e o DB2 demonstraram que os encadeamentos apresentam tantos problemas quanto solucionam. (...)

Então, novamente ... eu não tenho absolutamente nenhuma idéia dos méritos acima. Foi apenas muito tempo para caber em um comentário.

Denis de Bernardy
fonte
-3

Um banco de dados multithread só beneficiará você quando você tiver mais de uma consulta paralela no banco de dados. Depende do número de usuários que você possui. Se você tiver mais de dez usuários trabalhando no aplicativo ao mesmo tempo, provavelmente eles produzirão mais de uma consulta no banco de dados ao mesmo tempo.

Além disso, um banco de dados multithread só pode se beneficiar quando houver vários núcleos na CPU. Se houver um núcleo único, o banco de dados multiencadeado precisará enfileirar o trabalho e executá-los sequencialmente no núcleo único. Quando há vários núcleos, cada núcleo pode executar um thread em paralelo. Assim, melhor desempenho.

Isso responde à sua consulta?

oazabir
fonte
7
Bancos de dados multithread são benéficos mesmo em sistemas de núcleo único. Impede que uma única consulta de longa duração bloqueie todos os outros acessos ao banco de dados, e você pode ter vários threads aguardando no disco ou na E / S de rede, enquanto outro segmento está analisando ativamente consultas, processando dados pré-buscados etc.
Um usuário pode estar usando um programa que paraleliza algumas operações. Esse programa provavelmente se beneficiaria se o banco de dados também tivesse recursos de multi-threading / multi-processing.
Joanolo