2009-05-12 8 views
6

Si tengo dos consultas¿El número de columnas devueltas afecta la velocidad de una consulta?

SELECT Id, Forename, Surname 
FROM Person 
WHERE PersonName Like(‘%frank%’) 

Y

SELECT * 
FROM Person 
WHERE PersonName Like(‘%frank%’) 

Qué consulta se ejecutará más rápido? ¿La cláusula where/table se une al factor más grande, o la cantidad de columnas devueltas?

Pregunto porque estoy construyendo una serie de objetos que se asignan a las tablas de la base de datos. Normalmente, cada objeto tendrá al menos estos tres métodos:

Select - Selecciona todo

List - Selecciona lo suficiente que es se puede utilizar para rellenar una lista desplegable

Search - Selecciona todo lo que es visible en la resultados, típicamente alrededor de 6 o más columnas.

Si cada consulta devuelve exactamente el mismo conjunto de columnas del mantenimiento y pruebas del código debería ser más trivial. Es poco probable que la base de datos obtenga más de 50,000 filas en cualquier tabla dada, por lo que si la diferencia en el rendimiento es pequeña, tomaré el ahorro en tiempo de desarrollo. Si el rendimiento va a caer por el suelo, entonces trabajaré desde un ángulo diferente.

Por lo tanto, para la facilidad de desarrollo, es SELECT * sensible, o es ingenuo?

+3

Solo un poco de gramática: * afecta * la velocidad de una consulta. –

+0

http://xkcd.com/326/ – Quassnoi

+0

La política exterior puede afectar algo, pero un número de columnas no puede – Andomar

Respuesta

23

Es mejor evitar SELECT *

  • Se lleva a confusión cuando se cambia el diseño de la mesa.
  • Selecciona columnas innecesarias, y sus paquetes de datos se hacen más grandes.
  • Las columnas se pueden obtener los nombres duplicados, lo que tampoco es bueno para algunas aplicaciones
  • Si todas las columnas que necesita están cubiertos por un índice, SELECT columns sólo utilizará este índice, mientras que SELECT * tendrá que visitar a los registros de la tabla a obtén los valores que no necesitas También es malo para el rendimiento.
+0

Estoy de acuerdo con la mayoría de sus puntos, pero "Las columnas pueden obtener nombres duplicados", eso es nuevo para mí. ¿Cómo es eso? – paxdiablo

+2

@Pax: si tiene una autocombinación dentro de la consulta, o una dos tablas que tienen algunas columnas con los mismos nombres. – Quassnoi

+0

@Pax Select * From Person p, Contact c Donde c.PersonID = p.PersonID; esto normalmente tendrá [Nombre] en las 2 tablas, por ejemplo – balexandre

-2

Claro. Mejor nombre las columnas que deseas recuperar.

0

Si la persona solo tiene Id, Forename y Apellido, las consultas deben ser equivalentes. Sin embargo, el tiempo de consulta crecerá proporcionalmente al número de columnas (realmente cantidad de datos) devuelto.

Además, si la consulta solo va a necesitar esas tres columnas, solo debe solicitarlas. Si SELECCIONAS * y cambias el esquema más tarde, básicamente solo estás agregando procesamiento adicional a todas tus consultas sin un beneficio agregado real.

0

volveremos a este question sobre por qué usar el "SELECT *" no se prefiere constructo.

En mi experiencia seleccionando 3 columnas frente a select * en una tabla de 3 columnas que no tenga un rendimiento notable impacto en cuanto a pero como tablas se hacen más grandes y más amplio que se dará cuenta de una diferencia de rendimiento.

0

En general, en cualquier situación, que desea permanecer lejos de usar

SELECT * FROM TABLE 

en el código. Hacerlo puede generar varios problemas, de los cuales solo uno es el rendimiento. Otros dos en los que puedo pensar son la utilización de recursos (si seleccionas columnas que no necesitas, o alguien agrega columnas más tarde ... estás recuperando datos y desperdiciando memoria) y la legibilidad del código (si alguien ve SELECT * FROM en su código ... no necesariamente sabrán qué columnas se están usando realmente en su aplicación).

Solo un par de cosas en que pensar ... pero la mejor práctica es NO usarlo.

0

Sí lo hace. Básicamente:

  • Más datos tienen que ser transferido desde el servidor de base de datos del servidor
  • La base de datos tiene que ir a buscar más datos

Usted no debe usar select *

0

Además de la otras respuestas, considere que SELECT * devolverá los datos de todas las tablas en la consulta. Comience a agregar otras tablas a través de JOINs, y comenzará a ver cosas que no desea ver.

Creo que también he visto casos en los que SELECCIONAR * requiere que los datos se obtengan realmente de una tabla unida, en lugar de solo usar los índices en esa tabla para ayudar a restringir el conjunto de resultados general. Sin embargo, no puedo pensar en un ejemplo de eso.

1

Si recuerdas correctamente de la universidad (y ha pasado un tiempo), no es preferible seleccionar *, pero no tan malo, hasta que comiences a unirte. Cuando te metes en la alegbra relacional de crear las tuplas unidas, cada columna agrega tiempo, así que definitivamente lo evitaría si fuera posible.

6

SELECT * generalmente nunca es una buena idea. Puede que no disminuya la velocidad de carga de su DBMS, pero probablemente genere más datos de los que se necesitan en la red.

Sin embargo, es probable que se inutilice mediante el uso de la cláusula LIKE '%frank%' que básicamente no es indexable y dará como resultado una exploración completa de la tabla.

Es posible que desee considerar la limpieza de los datos cuando ingresa a la base de datos, ya que es casi seguro que las consultas subsiguientes se ejecutarán mucho más rápido.

Si lo que busca es franca, a continuación, asegúrese de que está almacenado como franca y uso:

select x,y,z from table where name = 'frank' 

Si usted desea conseguir Franklin, así, su uso:

select x,y,z from table where name like 'frank%' 

Ambos se poder usar un índice en la columna de nombre, "%frank%" no lo hará.

0

Hay varias dimensiones en esto. Por una vez, * hará que su código sea más frágil. Cuando en versiones posteriores cambia el diseño de la tabla, el código que se basa en el orden de las columnas puede romperse, o podría no ser sino leer o modificar las columnas incorrectas si los tipos de datos aún coinciden, lo que puede ser un problema realmente desagradable.

Además, si siempre solicita todas las columnas, necesitará más memoria en su cliente de base de datos y el servidor de la base de datos para las columnas innecesarias. Esto puede ser realmente costoso si la tabla contiene campos de caracteres largos, muchos campos y/o BLOB. Seleccionar columnas innecesarias también afectará la memoria caché del servidor inundándola con contenidos superfluos que nunca son examinados por un cliente.

Por lo tanto, en general no debe usarlo. La mayoría de las herramientas de mapeo relacional de objetos generan SQL que contiene todos los nombres de columna de todos modos, por lo que durante el desarrollo esto probablemente no sea un problema. Personalmente, solo uso * las consultas rápidas ad-hoc que debo escribir manualmente.

1

El número de columnas en la tabla no afecta el rendimiento de su consulta. La cantidad de columnas operadas en la consulta lo hará.

Nota el siguiente ejemplo del manual de conceptos de Oracle:

formato de filas y tamaño de Oracle almacena cada fila de una tabla de base de datos que contiene los datos por menos de 256 columnas como uno o más piezas fila. Si se puede insertar una fila completa en un solo bloque de datos , Oracle almacena la fila como una fila. Sin embargo, si todos los datos de una fila no se puede insertar en un bloque único de datos o si una actualización de una fila existente hace que la fila para superan su bloque de datos, Oracle almacena la fila usando múltiples filas piezas. Un bloque de datos generalmente contiene solo una fila por cada fila. Cuando Oracle debe almacenar una fila en más de una fila, está encadenado a través de múltiples bloques.

Cuando una tabla tiene más de 255 columnas, filas que tienen datos después de la columna 255a es probable que estar encadenado dentro del mismo bloque. Esto se denomina encadenamiento intrabloque . Las piezas de una fila encadenada se encadenan entre sí utilizando los rowids de las piezas. Con el encadenamiento intrabloque , los usuarios reciben todos los datos en el mismo bloque. Si la fila encaja en el bloque, los usuarios no ven el efecto en el rendimiento de E/S, porque no se requiere ninguna operación adicional de E/S para recuperar el resto de la fila.

Sin embargo: Si hay 400 columnas, que apostaría que la mayoría de las filas no cabrán en un solo bloque y por lo tanto verá una mucho más 'archivo db secuencial leer' que se requiere normalmente. Además, I recuerde que Steve Adams (o alguien hace mucho tiempo) mencionó que hay un costo adicional para acceder a una columna "más abajo en la lista" - lo siento, no tiene ese enlace.

+0

¿Esto también se aplica a MS Sql? – ilivewithian

2

Independientemente de los problemas de rendimiento, es una buena práctica enumerar siempre todos los campos en sus consultas.

  • ¿Qué sucede si decide agregar una columna TEXTO o BLOB en el futuro que se utiliza para una consulta en particular?Su SELECT * le devolverá los datos adicionales, lo necesite o no.
  • ¿Qué sucede si cambia el nombre de una columna? Su SELECT * siempre funcionará, pero el código de confianza se romperá.
0

Esta es la forma correcta y la más óptima. La razón es que solo recopila los datos necesarios, de modo que ocupa el espacio correcto (lo que necesita) para almacenar los datos antes de obtener los resultados.

SELECT Id, Forename, Surname 
FROM Person 
WHERE PersonName Like(‘%frank%’) 

Esto es incorrecto, ya que ocupa los campos no utilizados, que ocupa más espacio para ejecutar la consulta que ralentiza sus resultados. Incluso si tiene suerte y utiliza todos los campos en su consulta, es mejor enumerarlos individualmente. Esto aclarará la consulta y qué datos se devolverán a cualquier otro desarrollador que pueda necesitar modificar la consulta en el futuro.

SELECT * 
FROM Person 
WHERE PersonName Like(‘%frank%’) 
2

Para proyectos pequeños, generalmente puede salirse con select *. Sin embargo, es "correcto" no hacer eso. No notará ninguna diferencia de velocidad apreciable para una tabla en una consulta que no sea índice ... lo único que apreciablemente está haciendo es usar más ancho de banda para las columnas que no lee.

Dicho esto, notará una diferencia en las consultas de solo índice donde está llegando a la tabla completa cuando solo necesita acceder al índice. Esto especialmente surgirá cuando realices uniones.

Select * tiene usos, y si lo usa correctamente (por ejemplo, en combinación con un caché, asegurándose de que sea select table.*, y los resultados de direcciones por nombre de columna) puede reducir las consultas realizadas por su aplicación.

5

Voy a ir contra corriente aquí y digo que debe elegir el *. Creo que la optimización prematura es la raíz de muchos problemas, y es posible que descubra que no afecta su rendimiento cuando llega a la utilización real. Por supuesto, según el libro, es más lento, debe serlo, pero eso no significa que la diferencia sea importante en la práctica.

Algo a tener en cuenta, sin embargo, es que algunos motores SQL (MS-SQL seguro) almacenarán en caché el select *, por lo que si está utilizando una declaración preparada, o una vista o procedimiento almacenado que la tiene, Cambie el esquema de la tabla, no captará el cambio a menos que recompense la vista o sp, por lo que es una buena razón para evitar hacerlo si no está ejecutando estas consultas dinámicamente.

Y, por supuesto, esto varía según el motor de base de datos, por lo que una pequeña prueba de carga sería para asegurarse de que el impacto no sea obviamente grande.

0

la única vez que lo uso "select *" no evento es realmente un "select *"

en concreto: no

select count(*) from table

es que igual que

select count(ID) from table

la primero devuelve el número de filas en la tabla
pero el segundo devuelve el número de filas con un valor de ID NO NULO.

una distinción sutil pero vale la pena recordar.

+0

Otro uso aceptable de SELECT * está en la subconsulta de una cláusula EXISTS. – onedaywhen

0

SELECCIONAR * será más lento ya que tiene que transferir más datos. También debido a algunas otras razones ya mencionadas. Realmente se convierte en un problema cuando se unen las tablas, ya que comienza a agregar muchas más columnas, cuando en realidad todo lo que quiere hacer es unirse para que pueda filtrar.

Si realmente desea usar *, especifique la tabla que desea todas las columnas de, como SELECT persona. * De persona ...

Eso será reducir la cantidad de datos devueltos y hace que sea un poco más legible

0

Déjame jugar a los diablos abogar y sugerir un escenario donde SELECCIONAR * es una mejor opción. Supongamos que está creando una interfaz de usuario donde toma los resultados del conjunto de datos y los muestra en alguna forma de tabla o cuadrícula. Puede construir las columnas en la interfaz de usuario para hacer coincidir las columnas en el conjunto de datos y hacer SELECCIONAR * FROM MyView.

Al utilizar una vista en la base de datos, usted tiene control total sobre qué columnas son devueltas por la consulta y la interfaz de usuario puede ser lo suficientemente dinámica para mostrar todas las columnas. Los cambios en la vista se reflejarían inmediatamente en la interfaz de usuario sin recompilarlos y re0. Obviamente, sugeriría seguir el consejo anterior y especificar todas las columnas en la definición de la vista.

Acabo de pensar que, como a veces las personas se vuelven dogmáticas sobre seguir ciertas reglas y olvidan que el contexto importa.

Cuestiones relacionadas