sql >> Base de Datos >  >> RDS >> Mysql

¿Debo usar una función JOIN o ejecutar varias consultas en una estructura de bucle?

Ninguna de las dos soluciones propuestas es probablemente óptima, ¡PERO la solución 1 es IMPREDECIBLE y, por lo tanto, INHERENTEMENTE DEFECTUOSA!

Una de las primeras cosas que aprende cuando trabaja con grandes bases de datos es que "la mejor manera" de hacer una consulta a menudo depende de factores (conocidos como metadatos) dentro de la base de datos:

  • Cuántas filas hay.
  • Cuántas tablas está consultando.
  • El tamaño de cada fila.

Debido a esto, es poco probable que haya una solución milagrosa para su problema. Su base de datos no es la misma que la mía, deberá comparar diferentes optimizaciones si necesita el mejor rendimiento disponible.

Probablemente encontrará que aplicando y creando índices correctos (y comprender la implementación nativa de índices en MySQL) en su base de datos hace mucho más por usted.

Hay algunas reglas de oro con las consultas que rara vez se deben romper:

  • No los hagas en estructuras de bucle . A pesar de lo tentador que suele ser, la sobrecarga de crear una conexión, ejecutar una consulta y obtener una respuesta es alta.
  • Evitar SELECT * a menos que sea necesario . Seleccionar más columnas aumentará significativamente la sobrecarga de sus operaciones de SQL.
  • Conoce tus índices . Usa el EXPLAIN función para que pueda ver qué índices se están utilizando, optimizar sus consultas para usar lo que está disponible y crear nuevos.

Debido a esto, de los dos iría por la segunda consulta (reemplazando SELECT * con solo las columnas que desee), pero probablemente haya mejores formas de estructurar la consulta si tiene tiempo para optimizar.

Sin embargo, la velocidad NO sea ​​su única consideración en esto, hay una GRAN razón para no usar la sugerencia uno:

PREDICTABILIDAD:por qué los bloqueos de lectura son algo bueno

Una de las otras respuestas sugiere que tener la tabla bloqueada durante un largo período de tiempo es algo malo y que, por lo tanto, la solución de consultas múltiples es buena.

Yo diría que esto no podría estar más lejos de la verdad . De hecho, diría que, en muchos casos, la previsibilidad de ejecutar un solo bloqueo SELECT la consulta es un argumento mayor PARA ejecutar esa consulta que los beneficios de optimización y velocidad.

En primer lugar, cuando ejecutamos un SELECT (solo lectura) en una base de datos MyISAM o InnoDB (sistemas predeterminados para MySQL), lo que sucede es que la tabla está bloqueada en lectura. Esto evita que ocurra cualquier operación de ESCRITURA en la tabla hasta que se entregue el bloqueo de lectura (ya sea nuestro SELECT la consulta se completa o falla). Otro SELECT las consultas no se ven afectadas, por lo que si está ejecutando una aplicación de subprocesos múltiples, seguirán funcionando.

Este retraso es algo BUENO. ¿Por qué, usted puede pedir? Integridad de datos relacionales.

Tomemos un ejemplo:estamos ejecutando una operación para obtener una lista de elementos que se encuentran actualmente en el inventario de un grupo de usuarios en un juego, por lo que hacemos esta combinación:

SELECT * FROM `users` JOIN `items` ON `users`.`id`=`items`.`inventory_id` WHERE `users`.`logged_in` = 1;

¿Qué sucede si, durante esta operación de consulta, un usuario intercambia un artículo con otro usuario? Con esta consulta, vemos el estado del juego tal como estaba cuando iniciamos la consulta:el elemento existe una vez, en el inventario del usuario que lo tenía antes de ejecutar la consulta.

Pero, ¿qué sucede si lo ejecutamos en bucle?

Dependiendo de si el usuario lo intercambió antes o después de que leamos sus detalles, y en qué orden leamos el inventario de los dos jugadores, hay cuatro posibilidades:

  1. El artículo podría mostrarse en el inventario del primer usuario (escanear usuario B -> escanear usuario A -> artículo intercambiado O escanear usuario B -> escanear usuario A -> artículo intercambiado).
  2. El artículo podría mostrarse en el inventario del segundo usuario (artículo intercambiado -> escanear usuario A -> escanear usuario B O artículo intercambiado -> escanear usuario B -> escanear usuario A).
  3. El elemento podría mostrarse en ambos inventarios (escanear usuario A -> artículo intercambiado -> escanear usuario B).
  4. El artículo podría mostrarse en ninguno de los inventarios del usuario (escanear usuario B -> artículo intercambiado -> escanear usuario A).

Lo que esto significa es que no podríamos predecir los resultados de la consulta ni garantizar la integridad relacional .

Si planea dar $ 5,000 al tipo con el ID de artículo 1000000 el martes a la medianoche, espero que tenga $ 10,000 a mano. Si su programa se basa en elementos únicos que son únicos cuando se toman instantáneas, es posible que genere una excepción con este tipo de consulta.

El bloqueo es bueno porque aumenta la previsibilidad y protege la integridad de resultados.

Nota:puede forzar el bloqueo de un ciclo con una transacción , pero todavía ser más lento.

Ah, y finalmente, ¡UTILICE DECLARACIONES PREPARADAS!

nunca debes tiene una declaración que se parece a esto:

mysqli_query("SELECT * FROM Table2 WHERE ColumnAId=" . $row['ColumnAId'], $con);

mysqli tiene soporte para sentencias preparadas . Lea acerca de ellos y utilícelos, le ayudarán a evitar que algo terrible le suceda a su base de datos .