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:
- 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).
- 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).
- O item pode ser exibido em ambos inventários (digitalizar usuário A -> item negociado -> verificar usuário B).
- 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
.