Muchas columnas frente a pocas tablas: rendimiento inteligente

12

Sí, soy consciente de que la normalización de datos debería ser mi prioridad (tal como es).

  1. Tengo una tabla con 65 columnas que almacenan los datos del vehículo con columnas: used_vehicle, color, doors, mileage, pricey así sucesivamente, en total 65.
  2. Ahora, puedo dividir eso y tener una Vehiclemesa, VehicleInterior, VehicleExterior, VehicleTechnical, VehicleExtra(todo lo que uno-a-uno con el principal Vehicletabla).

Supongamos que tendré alrededor de 5 millones de filas (vehículos).

Encendido SELECTcon una WHEREcláusula: ¿El rendimiento será mejor buscando (ambos casos indexados al menos en IDs):

  1. Vehicle mesa con 65 columnas o
  2. Vehicletabla con JOINSotras cuatro tablas (todas con 5 millones de filas) para devolver todos los datos relacionados Vehicle?

(Según el motor de base de datos, considere PostgreSQL y / o MySQL).

¿Aprecia realmente alguna información detallada que pueda tener de su experiencia previa?

Urim Kurtishi
fuente
1
Una de las razones de hacer esto (partición vertical) es si tiene preguntas que tienen que ver con las columnas de VehicleInterior, otras consultas que tienen que ver con las columnas de única VehicleTechnical, etc., o si hay muchas filas / vehículos que no tienen absolutamente ninguna información sobre (por ejemplo) VehicleExtrapor lo en lugar de muchas filas con muchos valores nulos en una tabla, tiene filas en el resto de las tablas y ninguna fila enVehicleExtra
ypercubeᵀᴹ

Respuestas:

14

Suponiendo que estamos hablando de relaciones 1: 1 entre todas las tablas.

El almacenamiento general es prácticamente siempre (sustancialmente) más barato con una sola tabla en lugar de varias tablas en una relación 1: 1. Cada fila tiene 28 bytes de sobrecarga, más típicamente unos pocos bytes más para relleno adicional. Y debe almacenar la columna PK con cada tabla. Y tenga un índice separado (redundante) en cada una de estas columnas ... El tamaño sí importa para el rendimiento.

Esto es incluso cierto si muchas columnas son NULL en la mayoría de las filas porque el almacenamiento NULL es muy barato :

Al recuperar todas las columnas, una sola tabla es sustancialmente más rápida que 5 tablas unidas. También es mucho más simple . Puede ser difícil unir cinco tablas si no todas las filas están presentes en todas las tablas. Con WHEREcondiciones dirigidas a una sola tabla, es bastante fácil agregar otras tablas LEFT JOIN. No es tan trivial si tiene predicados en varias tablas ...

La partición vertical aún puede mejorar el rendimiento de ciertas consultas. Por ejemplo, si el 90% de sus consultas recuperan las mismas 5 columnas de las 65 disponibles, esto sería más rápido con una tabla que solo contenga estas 5 columnas.

OTOH, es posible que pueda atender tales consultas en unas pocas columnas seleccionadas con un índice de "cobertura" que permita escaneos de solo índice .

Otro candidato para la partición vertical: si tiene muchas actualizaciones en solo unas pocas columnas, mientras que el resto casi nunca cambia. Podría ser considerablemente más barato dividir filas en tal caso, ya que Postgres escribe una nueva versión de fila para cada actualización. Hay excepciones para grandes valores almacenados fuera de línea ("TOASTed"). Más detalles:

Realmente depende de la situación completa. En caso de duda, opte por la solución simple de tener una sola mesa, especialmente si representa bien la realidad: en su ejemplo, esos son todos los atributos de un automóvil y tienen sentido juntos.

Erwin Brandstetter
fuente
las actualizaciones serán raras si ninguna y las selecciones serán principalmente para todas las columnas (página de detalles del vehículo) e información principal (pocas columnas) para la lista de resultados de búsqueda, y de hecho tal vez la mejor solución sería dos tablas: una con información principal (pocas columnas ) y la otra tabla con el resto de las columnas. Entonces, en este caso, ¿cuál es su opinión sobre las uniones SQL con, digamos, 5 millones de filas, en cuanto al rendimiento? Por cierto, gracias por tu esfuerzo detallado
Urim Kurtishi
1
@octavius: una única tabla con un índice de varias columnas en las pocas columnas para permitir escaneos de solo índice para la lista de resultados podría ser la mejor ruta. (Tenga en cuenta que la secuencia de columnas es importante en los índices btree ). Las uniones no son tan caras, pero aún así serán más rápidas sin unirlas. El tamaño de almacenamiento agregado y la dispersión de datos para varias tablas puede ser la mayor desaceleración (más páginas de datos para leer para cada consulta).
Erwin Brandstetter
1
Estoy de acuerdo con el comentario de Erwins de que la respuesta realmente dependerá de la situación completa o del uso en el mundo real. Si descubrió que el 90% de las consultas estaban en un pequeño subconjunto de datos y el rendimiento era absolutamente primordial, entonces puede haber razones para justificar el esfuerzo adicional dividido en muchas tablas. Personalmente, trataría de mantener el modelo de datos simple. Además, ¿qué tan rápido es lo suficientemente rápido? ¿Cuánto esfuerzo haces para salvar ese último milisegundo? ¿Has intentado burlarte de algún dato y hacer alguna prueba?
Sir Swears-a-lot
@ErwinBrandstetter que mencionaste en tu respuesta que la relación es 1: 1. ¿Qué pasa con las naves de relación 1: N?
Slim
Para una relación 1: N, necesita dos tablas separadas de todos modos. Excepto si agrupa varias filas en una matriz o tipo de documento. Entonces depende. Los principios descritos aquí se aplican independientemente. Sus patrones de acceso y estrategias de índice pueden marcar la diferencia. Haga una nueva pregunta si desea ser más específico.
Erwin Brandstetter
0

Una selección en una sola tabla siempre debe ser más rápida. Tan pronto como haya encontrado su vehículo, ya tiene todos los detalles.

Sin embargo, pierde la eficiencia de la normalización. Por ejemplo, si 1 automóvil tuviera muchos modelos con diferentes opciones.

¿Es esta una base de datos de referencia de todos los automóviles? ¿O una lista de vehículos de segunda mano? ¿Habría muchos ejemplos de la misma marca / modelo con las mismas opciones?

Editar: debería calificar mi respuesta como rdbms genérico en lugar de postgres específico. Me remito a la respuesta detallada de @ Erwin específica para postgres

Sir jura mucho
fuente
2
"Una selección en una sola tabla siempre debe ser más rápida". ¿Por qué?
ypercubeᵀᴹ
vehiclemake y vehiclemodel son tablas diferentes, por lo que la tabla de vehículo tiene claves externas de vehiclemake y vehiclemodel. No creo que la normalización sea un problema aquí. Entiendo que seleccionar en una sola tabla sería más rápido, sin embargo, tenemos una situación diferente, ¿cómo afectará la fila con muchas columnas al rendimiento y así sucesivamente frente a las tablas con menos columnas (pero pocas tablas - 5 de ellas con combinaciones)
Urim Kurtishi
Lo siento, me había perdido el punto de que la marca y el modelo ya estaban separados. La versión corta es que las uniones requieren esfuerzo para el motor de la base de datos. Si usa una sola tabla / fila, obtendrá todo en una sola selección, lo que resultaría en menos E / S y sobrecarga para el motor db.
Sir Swears-a-lot