Is SQL Query in Loops a good practice?

Asked

Viewed 826 times

4

Ride query with Where or other sql commands within loops like Foreach is it a good practice or not recommended at all? There is a better way to treat the data without having to make so many calls in the database?

  • 5

    It depends. You could be more clear about what you intend to do?

1 answer

9

TL;DR: No, it’s not good practice.

Long answer:

As a general rule assume that it is always best to insert as little as possible overhead in whatever process you are mapping.

In the case of several darlings being executed within a loop you are saturating the database with requests.

Saved the implementation differences between the Dbms, Each one has a cost: A query is interpreted, mapped, has its execution plan evaluated, its competition with other requests evaluated, memory pages reserved and indexes searched, among other processes.

That said, let’s go to some possibilities. I’ll list the method you described first.

In this simulation,

  • TABELA1 has 10 records
  • TABELA2 has 100 records
  • Foreign key: TABELA2.T1ID for TABELA1.ID
  • There are 10 records on TABELA2 for each record in TABELA1

Case 1: Serial calls

-- Primeira pesquisa no banco de dados. Retorna 10 registros.
> SELECT ID, NOME FROM TABELA1 T1
-- Loop. Uma chamada para cada linha no retorno da consulta acima:
> SELECT ID, NOME FROM TABELA2 T2 WHERE T2.T1ID = 1
> SELECT ID, NOME FROM TABELA2 T2 WHERE T2.T1ID = 2
> SELECT ID, NOME FROM TABELA2 T2 WHERE T2.T1ID = 3
> SELECT ID, NOME FROM TABELA2 T2 WHERE T2.T1ID = 4
> SELECT ID, NOME FROM TABELA2 T2 WHERE T2.T1ID = 5
> SELECT ID, NOME FROM TABELA2 T2 WHERE T2.T1ID = 6
> SELECT ID, NOME FROM TABELA2 T2 WHERE T2.T1ID = 7
> SELECT ID, NOME FROM TABELA2 T2 WHERE T2.T1ID = 8
> SELECT ID, NOME FROM TABELA2 T2 WHERE T2.T1ID = 9
> SELECT ID, NOME FROM TABELA2 T2 WHERE T2.T1ID = 10
-- 11 chamadas são realizadas ao banco de dados.

Case 2: Concatenation via UNION

 -- Você pode concatenar suas chamadas dentro do loop,
 -- e solicitar uma única chamada.
 -- Primeira pesquisa no banco de dados. Retorna 10 registros.
> SELECT ID, NOME FROM TABELA1 T1
 -- Loop e concatenação. Uma chamada contendo o seguinte texto:
> SELECT ID, NOME FROM TABELA2 T2 WHERE T2.T1ID = 1 UNION
  SELECT ID, NOME FROM TABELA2 T2 WHERE T2.T1ID = 2 UNION
  SELECT ID, NOME FROM TABELA2 T2 WHERE T2.T1ID = 3 UNION
  SELECT ID, NOME FROM TABELA2 T2 WHERE T2.T1ID = 4 UNION
  SELECT ID, NOME FROM TABELA2 T2 WHERE T2.T1ID = 5 UNION
  SELECT ID, NOME FROM TABELA2 T2 WHERE T2.T1ID = 6 UNION
  SELECT ID, NOME FROM TABELA2 T2 WHERE T2.T1ID = 7 UNION
  SELECT ID, NOME FROM TABELA2 T2 WHERE T2.T1ID = 8 UNION
  SELECT ID, NOME FROM TABELA2 T2 WHERE T2.T1ID = 9 UNION
  SELECT ID, NOME FROM TABELA2 T2 WHERE T2.T1ID = 10
-- 2 chamadas são realizadas ao banco de dados.

Case 3: Clause IN

-- Vários SGBDs implementam a cláusula IN:
-- Primeira pesquisa no banco de dados. Retorna 10 registros.
> SELECT ID, NOME FROM TABELA1 T1
-- Loop e concatenação em um único parâmetro:
> SELECT ID, NOME FROM TABELA2 T2 WHERE T2.T1ID IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
-- 2 chamadas. Muito menos conteúdo a ser interpretado
-- pelo SGDB do que o caso 3.

Case 4a: Subquery

> SELECT ID, NOME
  FROM TABELA2 T2
  WHERE T2.T1ID IN
     (
        SELECT ID
        FROM TABELA1 T1
     )
-- Uma única chamada ao banco.

Case 4b: JOIN

> SELECT ID, NOME 
    FROM TABELA2 T2
    JOIN TABELA1 T1
      ON T2.T1ID = T1.ID
-- Uma única chamada ao banco. Em alguns SGDBs, mais performático do que 4a.
  • 2

    I would recommend testing each of these options in the actual application before deciding. Each case is a case, it is difficult to know which is the most performative option without testing.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.