Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Devo usar uma função JOIN ou executar várias consultas em uma estrutura de loop?

Nenhuma das duas soluções propostas são provavelmente ótimas, MAS a solução 1 é IMPREVISÍVEL e, portanto, INERENTEMENTE FALHA!


Uma das primeiras coisas que você aprende ao lidar com grandes bancos de dados é que 'a melhor maneira' de fazer uma consulta geralmente depende de fatores (chamados de metadados) dentro do banco de dados:
  • Quantas linhas existem.
  • Quantas tabelas você está consultando.
  • O tamanho de cada linha.

Por causa disso, é improvável que haja uma solução mágica para o seu problema. Seu banco de dados não é o mesmo que meu banco de dados, você precisará avaliar diferentes otimizações se precisar do melhor desempenho disponível.

Você provavelmente descobrirá que aplicando e construindo índices corretos (e entender a implementação nativa de índices no MySQL) em seu banco de dados faz muito mais por você.

Existem algumas regras de ouro com consultas que raramente devem ser quebradas:
  • Não faça isso em estruturas de loop . Por mais tentador que seja, a sobrecarga de criar uma conexão, executar uma consulta e obter uma resposta é alta.
  • Evite SELECT * a menos que necessário . A seleção de mais colunas aumentará significativamente a sobrecarga de suas operações SQL.
  • Conheça seus índices . Use o EXPLAIN recurso para que você possa ver quais índices estão sendo usados, otimizar suas consultas para usar o que está disponível e criar novos.

Por causa disso, das duas eu iria para a segunda consulta (substituindo SELECT * apenas com as colunas desejadas), mas provavelmente há maneiras melhores de estruturar a consulta se você tiver tempo para otimizar.

No entanto, a velocidade NÃO seja sua única consideração nisso, há uma GRANDE razão para não usar a sugestão um:

PREDITABILIDADE:por que os bloqueios de leitura são uma coisa boa


Uma das outras respostas sugere que ter a tabela bloqueada por um longo período de tempo é uma coisa ruim e que, portanto, a solução de consulta múltipla é boa.

Eu diria que isso não poderia estar mais longe da verdade . Na verdade, eu diria que, em muitos casos, a previsibilidade de executar um único bloqueio SELECT query é um argumento maior para executar essa consulta do que os benefícios de otimização e velocidade.

Em primeiro lugar, quando executamos um SELECT (somente leitura) em um banco de dados MyISAM ou InnoDB (sistemas padrão para MySQL), o que acontece é que a tabela é bloqueada para leitura. Isso evita que qualquer operação WRITE aconteça na tabela até que o bloqueio de leitura seja entregue (ou nosso SELECT consulta é concluída ou falha). Outro SELECT as consultas não são afetadas, portanto, se você estiver executando um aplicativo multithread, elas continuarão funcionando.

Esse atraso é bom. Por que, você pode perguntar? Integridade de dados relacionais.

Vamos dar um exemplo:estamos executando uma operação para obter uma lista de itens atualmente no inventário de um grupo de usuários em um jogo, então fazemos esta junção:
SELECT * FROM `users` JOIN `items` ON `users`.`id`=`items`.`inventory_id` WHERE `users`.`logged_in` = 1;

O que acontece se, durante esta operação de consulta, um usuário trocar um item com outro usuário? Usando essa consulta, vemos o estado do jogo como estava quando iniciamos a consulta:o item existe uma vez, no inventário do usuário que o possuía antes de executarmos a consulta.

Mas, o que acontece se estivermos executando em um loop?


Dependendo se o usuário o negociou antes ou depois de lermos seus detalhes e em qual ordem lemos o inventário dos dois jogadores, existem quatro possibilidades:
  1. O item pode ser mostrado no inventário do primeiro usuário (digitalizar usuário B -> digitalizar usuário A -> item negociado OU digitalizar usuário B -> digitalizar usuário A -> item negociado).
  2. O item pode ser mostrado no inventário do segundo usuário (item negociado -> digitalizar usuário A -> digitalizar usuário B OU item negociado -> digitalizar usuário B -> digitalizar usuário A).
  3. O item pode ser exibido em ambos inventários (digitalizar usuário A -> item negociado -> verificar usuário B).
  4. O item pode ser mostrado em nenhum dos estoques do usuário (digitalizar usuário B -> item negociado -> verificar usuário A).

O que isso significa é que não poderíamos prever os resultados da consulta ou garantir a integridade relacional .

Se você está planejando dar $ 5.000 para o cara com o item ID 1000000 à meia-noite de terça-feira, espero que você tenha $ 10k em mãos. Se o seu programa depende de itens únicos serem únicos quando os instantâneos são tirados, você possivelmente levantará uma exceção com esse tipo de consulta.

Bloquear é bom porque aumenta a previsibilidade e protege a integridade de resultados.

Observação:você pode forçar o bloqueio de um loop com uma transação , mas ainda seja mais lento.

Ah, e finalmente, USE DECLARAÇÕES PREPARADAS!


Você deve nunca tem uma declaração que se parece com isso:
mysqli_query("SELECT * FROM Table2 WHERE ColumnAId=" . $row['ColumnAId'], $con);

mysqli tem suporte para instruções preparadas . Leia sobre eles e use-os, eles ajudarão você a evitar algo terrível acontecendo com seu banco de dados .