Estou tentando descobrir se existe uma linha em uma tabela. Usando o MySQL, é melhor fazer uma consulta como esta:
SELECT COUNT(*) AS total FROM table1 WHERE ...
e verifique se o total é diferente de zero ou se é melhor fazer uma consulta como esta:
SELECT * FROM table1 WHERE ... LIMIT 1
e verifique se alguma linha foi retornada?
Nas duas consultas, a cláusula WHERE usa um índice.
sql
mysql
performance
exists
Bernard Chen
fonte
fonte
...EXISTS( SELECT 1/0 FROM someothertable)
. Para SQL Server e Oracle - não faz diferença usar *, 1 ou NULL porque EXISTS apenas testa um booleano com base em mais de 1 dos critérios WHERE correspondentes.SELECT 1 FROM table1 WHERE col = $var LIMIT 1
é mais rápida que a sua consulta. Então, qual é a vantagem da sua consulta?Eu fiz algumas pesquisas sobre esse assunto recentemente. A maneira de implementá-lo deve ser diferente se o campo for um campo TEXT, um campo não exclusivo.
Eu fiz alguns testes com um campo de texto. Considerando o fato de termos uma tabela com entradas de 1 milhão. 37 entradas são iguais a 'alguma coisa':
SELECT * FROM test WHERE texte LIKE '%something%' LIMIT 1
commysql_num_rows()
: 0.039061069488525s. (MAIS RÁPIDO)SELECT count(*) as count FROM test WHERE text LIKE '%something%
: 16.028197050095s.SELECT EXISTS(SELECT 1 FROM test WHERE text LIKE '%something%')
: 0.87045907974243s.SELECT EXISTS(SELECT 1 FROM test WHERE text LIKE '%something%' LIMIT 1)
: 0.044898986816406s.Mas agora, com um campo BIGINT PK, apenas uma entrada é igual a '321321':
SELECT * FROM test2 WHERE id ='321321' LIMIT 1
commysql_num_rows()
: 0.0089840888977051s.SELECT count(*) as count FROM test2 WHERE id ='321321'
: 0.00033879280090332s.SELECT EXISTS(SELECT 1 FROM test2 WHERE id ='321321')
: 0.00023889541625977s.SELECT EXISTS(SELECT 1 FROM test2 WHERE id ='321321' LIMIT 1)
: 0.00020313262939453s. (MAIS RÁPIDO)fonte
SELECT 1 FROM test WHERE texte LIKE '%something%' LIMIT 1
select 1 ... limit 1
, é inútil para surround com select existeSELECT 1 FROM test WHERE ...
, semSELECT EXISTS
contornos. Presumivelmente, é um cabelo mais rápido assim.Um pequeno exemplo da resposta de @ ChrisThompson
Exemplo:
Usando um alias:
fonte
Na minha pesquisa, posso encontrar o resultado seguindo a velocidade.
fonte
Acho que vale a pena ressaltar, embora tenha sido abordado nos comentários, que nesta situação:
É superior a:
Isso ocorre porque a primeira consulta pode ser satisfeita pelo índice, enquanto a segunda exige uma consulta de linha (a menos que possivelmente todas as colunas da tabela estejam no índice usado).
A adição da
LIMIT
cláusula permite que o mecanismo pare após encontrar qualquer linha.A primeira consulta deve ser comparável a:
Que envia os mesmos sinais para o mecanismo (1 / * não faz diferença aqui), mas eu ainda escreveria o 1 para reforçar o hábito ao usar
EXISTS
:Pode fazer sentido adicionar o
EXISTS
agrupamento se você precisar de um retorno explícito quando nenhuma linha corresponder.fonte
Sugira que você não use,
Count
porque count sempre cria cargas extras para uso no banco de dadosSELECT 1
e retorna 1 se o seu registro estiver ali, caso contrário, ele retornará nulo e você poderá lidar com isso.fonte
Uma consulta COUNT é mais rápida, embora talvez não visivelmente, mas na medida em que obtém o resultado desejado, ambas devem ser suficientes.
fonte
Às vezes, é bastante útil obter a chave primária de incremento automático (
id
) da linha, se ela existir e0
se não .Veja como isso pode ser feito em uma única consulta:
fonte
IFNULL(id, 0)
aqui em vez doCOUNT(*)
?Para tabelas não-InnoDB, você também pode usar as tabelas de esquema de informações:
http://dev.mysql.com/doc/refman/5.1/en/tables-table.html
fonte
Eu iria com
COUNT(1)
. É mais rápido do queCOUNT(*)
porqueCOUNT(*)
testa para ver se pelo menos uma coluna nessa linha é! = NULL. Você não precisa disso, principalmente porque você já tem uma condição em vigor (aWHERE
cláusula).COUNT(1)
em vez disso, testa a validade de1
, que é sempre válida e leva muito menos tempo para testar.fonte
Ou você pode inserir parte sql bruta nas condições para que eu tenha 'conditions' => array ('Member.id NOT IN (SELECT Membership.member_id FROM members AS AS Membership)')
fonte
COUNT(*)
são otimizados no MySQL, portanto a consulta anterior provavelmente será mais rápida, de um modo geral.fonte