Sarebbe meglio riscrivere la query come:
SELECT payments.*
FROM customers
JOIN payments
ON payments.id_customer = customers.id
WHERE customers.id_project = 5
Mentre questo sembra meno conciso e un buon pianificatore di query vedrà cosa stai cercando di fare ed eseguirà la tua sottoquery correlata come il join precedente invece, un cattivo pianificatore di query potrebbe finire per fare una scansione dell'indice di payments.id_customer
(supponendo che tu abbia un indice rilevante ) (o peggio, scansione della tabella) invece di fare le cose nel modo più efficiente. Anche un buon pianificatore di query potrebbe non vedere l'ottimizzazione se la disposizione di questa query è racchiusa in qualcosa di più complicato. Esprimere la relazione come join anziché come query secondaria può fare più differenza che modificare la struttura dei dati.
Come dice Jeff, qualsiasi denormalizzazione dovrebbe essere considerata con attenzione: può portare a un semplice aumento delle prestazioni, in particolare per alcuni scopi di reportistica, ma può portare a incongruenze dovute a bug nella logica aziendale di supporto.
Come nota a margine: ovviamente non conosco i tuoi affari, quindi potrei mancare qualcosa, ma le tue relazioni con i tavoli mi sembrano strane. Implica che non puoi mai avere più di un progetto con lo stesso cliente, cosa che di solito non è vera nella mia esperienza, almeno per un lungo periodo.
customer project payment
-------- -------- -------
pa_id
pr_id <-- payment
cu_id <-- customer
o se essere meno normalizzato (anche se dubito che sarebbe necessario):
customer project payment
-------- -------- --------
pa_id
pr_id <-- payment
cu_id <-- customer
`------------- customer
Ovviamente, ciò sconta ancora la possibilità di un progetto congiunto con due clienti ...