Mysql selecciona dónde no está en la tabla

Tengo 2 tablas (A y B) con las mismas teclas principales. Quiero seleccionar todas las filas que están en A y no en B. Lo siguiente funciona:

select * from A where not exists (select * from B where A.pk=B.pk); 

sin embargo, parece bastante malo (~ 2 segundos en solo 100k filas en A y de 3 a 10k menos en B)

¿Hay una mejor manera de ejecutar esto? Tal vez como una izquierda unirse?

 select * from A left join B on Ax=By where By is null; 

Según mis datos, esto parece funcionar un poco más rápido (~ 10%), pero ¿qué ocurre en general?

Yo uso consultas en el formato de tu segundo ejemplo. Una unión suele ser más escalable que una subconsulta correlacionada.

Creo que tu última statement es la mejor manera. También puedes probar

 SELECT A.* from A left join B on Ax = By where By is null 

También uso uniones izquierdas con un criterio de tipo “where table2.id is null”.

Ciertamente, parece ser más eficiente que la opción de consulta anidada.

Las uniones generalmente son más rápidas (en MySQL), pero también debe considerar su esquema de indexación si observa que aún se mueve lentamente. En general, cualquier configuración de campo como una clave externa (usando INNODB) ya tendrá un conjunto de índices. Si está utilizando MYISAM, asegúrese de que todas las columnas de la statement ON estén indexadas, y considere agregar también columnas en la cláusula WHERE al final del índice, para convertirlo en un índice de cobertura. Esto permite que el motor tenga acceso a todos los datos necesarios en el índice, eliminando la necesidad de hacer un segundo viaje de ida y vuelta a los datos originales. Tenga en cuenta que esto afectará la velocidad de las inserciones / actualizaciones / eliminaciones, pero puede boost significativamente la velocidad de la consulta.

Esto me ayudó mucho. Joins son siempre más rápidas que las subconsultas para dar resultados:

 SELECT tbl1.id FROM tbl1 t1 LEFT OUTER JOIN tbl2 t2 ON t1.id = t2.id WHERE t1.id>=100 AND t2.id IS NULL ;