La tua ipotesi è falsa; la sottoquery verrà eseguita una sola volta. Il motivo per cui è più lento di un join è perché IN non può sfruttare gli indici; deve scansionare i suoi argomenti una volta per ogni volta che si trova WHERE La clausola viene valutata, ovvero una volta per riga nella tabellaA. Puoi ottimizzare la query, senza utilizzare variabili o stored procedure, semplicemente sostituendo il IN con un join, quindi:
SELECT tableA.field1, tableA.field2, [...]
FROM tableA
INNER JOIN tableB ON tableA.id = tableB.id
A meno che non ti dispiaccia recuperare tutti i campi di entrambe le tabelle, devi enumerare i campi che desideri in SELECT clausola; tableA.* , ad esempio, genererà un errore di sintassi.