2010-01-21 7 views
5

a menudo me encuentro con ganas de escribir una consulta SQL como la siguiente:SQL: ¿Es correcta una consulta como esta o hay una forma más eficiente de hacerlo, como usar una combinación?

SELECT body 
    FROM node_revisions 
where vid = (SELECT vid 
       FROM node 
       WHERE nid = 4); 

sé que hay une y esas cosas que podría hacer, pero parece que hacer las cosas más complicadas. ¿Se une una mejor manera de hacerlo? ¿Es más eficiente? ¿Más fácil de entender?

+1

Estoy dispuesto a apostar que, en SQL Server, esa consulta y la unión lógicamente equivalente tendrían idénticos planes de ejecución de consultas. – Dana

Respuesta

7

une tienden a ser más eficiente ya que las bases de datos se escriben con operaciones de conjuntos en cuenta (y combinaciones se establecen las operaciones).

Sin embargo, el rendimiento variará de la base de datos a la base de datos, cómo se estructuran las tablas, la cantidad de datos en ellos y cuánto será devuelto por la consulta.

Si la cantidad de datos es pequeña, usaría una subconsulta como la suya en lugar de una unión.

Esto es lo que una unión se vería así:

SELECT body 
FROM node_revisions nr 
INNER JOIN node n 
    ON nr.vid = n.vid 
WHERE n.nid = 4 

No utilizaría la consulta informados, ya que no hay posibilidad de más de un registro nodo con un nid = 4, lo que causaría que falle.

yo usaría:

SELECT body 
FROM node_revisions 
WHERE vid IN (SELECT vid 
      FROM node 
      WHERE nid = 4); 

esto es más legible o entendible? En este caso, es una cuestión de preferencia personal.

+0

Es mucho más que una preferencia personal. Me gustaría ver una unión en dos columnas usando IN que se compare en legibilidad. Honestamente, el uso excesivo de IN, para mí, puede ser un síntoma de un problema conceptual central en SQL. – ErikE

1
select 
    body 
from node_revisions A 
where exists (select 'x' 
       from Node B 
       Where A.Vid = B.Vid and B.NID=4) 
+2

¿Por qué es eso mejor? Parece más complicado. –

+0

Es más complicado pero tampoco está haciendo lo mismo. Esta es una semi unión, que en algunos casos permite que el servidor de la base de datos realice alguna optimización. También siempre solo devolverá una fila de la tabla principal sin importar cuántas filas coincidentes se encuentren en la tabla de subconsulta. Tenga en cuenta que no puede referir en la consulta principal a las columnas en la subconsulta, pero ese es el punto: está comprobando * existencia *, no extrayendo datos.Además, si la tabla de subconsulta tiene MUCHAS filas por fila en la tabla externa, la sintaxis existente puede ser mucho más eficiente, ya que puede detenerse después de encontrar solo una. – ErikE

+0

Esto no es lógicamente equivalente a la consulta original. En el caso de que la subconsulta devuelva varias filas, esto funcionará y la consulta original fallará. Esto sería un equivalente de una consulta con 'IN' en lugar de' = '. Sin embargo, todos los motores modernos pueden optimizar tanto 'EXISTS' como' IN' para una semi-unión. – Quassnoi

3

La respuesta a todas las preguntas relacionadas con el rendimiento de bases de datos es depende, y estamos cortos de datos en el OP. Sin conocer detalles acerca de su situación ... (por lo tanto, se trata de reglas generales)

combinaciones estén mejor y más fácil de entender

  • Si por alguna razón, tiene varias claves de columna (pescado) , puede seguir usando una combinación y simplemente virar en otra expresión a la condición de unión.
  • Si en el futuro realmente necesita unir datos auxiliares, el marco de unión ya está allí.
  • Hace que sea más claro exactamente a qué se está uniendo y dónde deben implementarse los índices.
  • El uso de combinaciones te hace mejor en combinaciones y mejor en pensar en combinaciones.
  • combinaciones estén claros acerca de qué tablas están en juego

consultas escritas no tienen nada que ver con effiency *

Las consultas que escribe y lo que realmente se ejecute tienen poco que ver entre sí. Hay muchas maneras de escribir una consulta, pero solo unas pocas formas de obtenerla, y depende del motor de consulta decidir. Esto se relaciona principalmente con índices. Es muy posible escribir cuatro consultas que se ven totalmente diferentes pero que internamente hacen lo mismo.

(* Es posible escribir una consulta horrible que es ineficiente, sino que se necesita un tipo especial de loco para hacer eso.)

select 
    body 

from node_revisions nr 

join node n 
on n.vid = nr.vid 

where n.nid = 4 
1

El último código de MySQL 6.x convierte automáticamente esa expresión en EN una unión interior utilizando un semi-unirse a la optimización sub consulta, por lo que las 2 declaraciones en gran medida equivalentes:

http://forge.mysql.com/worklog/task.php?id=3740

pero, en realidad la escritura a cabo es muy simple de hacer, porque INNER JOIN es el tipo de combinación predeterminado, y hacer esto no dependería de que el servidor lo optimice (lo que podría decidir por alguna razón y que no sería necesariamente portátil). todas las cosas son iguales, ¿por qué no van con:

select body from node_revisions r, node n where r.vid = n.vid and n.node = 4 
3

Creo que las uniones son más fáciles de entender y pueden ser más eficientes. Su caso es bastante simple, por lo que es probable que sea una sacudida. Así es como lo escribiría:

SELECT body 
    FROM node_revisions 
    inner join node 
     on (node_revisions.vid = node.vid) 
    WHERE node.nid = 4 
1

no veo nada de malo en lo que ha escrito, y un buen optimizador puede incluso cambiar a una unirse si lo considera oportuno.

1
SELECT body 
FROM node_revisions 
WHERE vid = 
     (
     SELECT vid 
     FROM node 
     WHERE nid = 4 
     ) 

Esta consulta es lógicamente equivalente a una unión si y sólo si es un nidPRIMARY KEY o está cubierta por una restricción UNIQUE.

De lo contrario, las consultas no son equivalentes: una unión siempre tendrá éxito, mientras que la subconsulta fallará si hay más de 1 fila en node con nid = 4.

Si nid es PRIMARY KEY, entonces el JOIN y la subconsulta tendrán el mismo rendimiento.

En caso de una combinación, node se hará conduce

En caso de una subconsulta, la sub consulta se ejecutará una vez y se transforma en un const en analizar el escenario.

+0

SÍ, nid y vid son claves principales únicas. –

+0

'@Brian T. Hannan': entonces las consultas son idénticas. 'JOIN' y la subconsulta realizarán lo mismo. – Quassnoi

2

una combinación es interesante:

select body 
from node_revisions nr 
join node n on nr.vid = n.vid 
where n.vid = 4 

Pero también se puede expresar una unión sin unirse a [!]:

select body 
from node_revisions nr, node n 
where n.nid = 4 and nr.vid = n.vid 

Curiosamente, SQL Server da una ligera plan de consulta diferente en ambos consultas, mientras que la unión tiene un análisis de índice agrupado, la "unión sin unión" tiene una búsqueda de índice agrupado en su lugar, lo que indica que es better, al menos en este caso.

Cuestiones relacionadas