Data

13 jan, 2017

Uso eficiente do mysqli_result::$num_rows

Publicidade

Eu frequentemente vejo esse padrão em aplicativos herdados usando mysqli:

$result = $mysqli->query("
    SELECT *
    FROM table_name
    WHERE conditions = 'whatever'
");
if ($result && $result->num_rows > 0) {
    return;
}

A intenção do desenvolvedor aqui é ver se existem quaisquer linhas no banco de dados que correspondam a uma determinada condição. Ele faz isso emitindo uma consulta. Em seguida, perguntando ao objeto do resultado quantas linhas ele tem. O desenvolvedor não quer realmente nenhum dado do resultado e não se preocupa com a contagem de linha em si; esta é apenas uma verificação para ver se ao menos uma linha existe no banco de dados.

Esta é uma má conservação de recursos. O banco de dados faz o trabalho necessário para selecionar todas as colunas para todas as linhas que correspondem às condições, aloca memória para elas e as retorna. Mas o desenvolvedor descarta tudo isso imediatamente.

Para fazer a mesma coisa, consultar uma única coluna e limitar os resultados a uma única linha consome menos recursos e é tão eficaz quanto:

$result = $mysqli->query("
    SELECT col_name
    FROM table_name
    WHERE conditions = 'whatever'
    LIMIT 1
");
if ($result && $result->num_rows > 0) {
    return;
}

Agora, o banco de dados só faz o trabalho necessário para uma única coluna e uma única linha.

(Como uma nota a ser observada, acho interessante que eu não tenha visto este padrão em projetos usando PDO. Não sei o porquê disso. Talvez haja algum código de exemplo de origem para mysqli em algum lugar que ganhou uma vida própria através da cópia e reutilização.)

(Atualização) Talvez uma melhor maneira de conservar os recursos, cortesia do usuário do Reddit marcabschmidt, é usar um COUNT () na consulta e, em seguida, buscar a contagem de linhas, algo parecido com isto…

$result = $mysqli->query("
    SELECT COUNT(*)
    FROM table_name
    WHERE conditions = 'whatever'
");
if ($result && $result->fetch_array()[0] > 0) {
    return;
}

… evitando assim o uso de mysqli_result :: $ num_rows completamente.

(Atualização 2) Muitos comentários no tópico Reddit acima. Para resumir este artigo: selecionar todas as colunas de todas as linhas, depois examinar $ num_rows e, em seguida, descartar o conjunto de resultados, é uma maneira terrível de determinar se há quaisquer linhas correspondentes no banco de dados. É trivial e algo muito melhor usar um LIMIT 1 e $ num_rows ou alguma forma de COUNT () ou talvez alguma outra abordagem.

 

***

Paul M. Jones faz parte do time de colunistas internacionais do iMasters. A tradução do artigo é feita pela redação iMasters, com autorização do autor, e você pode acompanhar o artigo em inglês no link: http://paul-m-jones.com/archives/6470