SQL Query on Loops is good practice?

4

Is query set with Where or other sql commands inside loops like Foreach good practice or not recommended at all? Is there a better way to handle the data without having to make so many calls in the database?

    
asked by anonymous 30.07.2014 / 14:11

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 overhead as possible into whatever process you are mapping.

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

The implementation differences between the DBMSs are saved, each has a cost: query is interpreted, mapped, has its execution plan evaluated, its competition with other queries evaluated, reserved memory pages and searched indexes, among other processes.

That said, let's get 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 to TABELA1 . ID
  • There are 10 records in 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: IN Clause

-- 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.
    
30.07.2014 / 15:53