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?
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?
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 recordsTABELA2
has 100 recordsTABELA2
.T1ID
for TABELA1
.ID
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.
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 mysql sql performance
You are not signed in. Login or sign up in order to post.
It depends. You could be more clear about what you intend to do?
– electus