¿Hay alguna razón para preocuparse por el orden de las columnas en una tabla?

84

Sé que puedes ALTERAR el orden de las columnas en MySQL con FIRST y DESPUÉS, pero ¿por qué querrías molestarte? Dado que las buenas consultas nombran explícitamente las columnas al insertar datos, ¿hay realmente alguna razón para preocuparse en qué orden están las columnas en la tabla?

Lynn
fuente

Respuestas:

94

El orden de las columnas tuvo un gran impacto en el rendimiento de algunas de las bases de datos que sintonicé, que abarcan Sql Server, Oracle y MySQL. Esta publicación tiene buenas reglas generales :

  • Primero las columnas de clave primaria
  • A continuación, columnas de clave externa.
  • Columnas buscadas con frecuencia a continuación
  • Columnas que se actualizan con frecuencia más adelante
  • Las columnas que aceptan valores NULL son las últimas.
  • Las columnas que aceptan valores NULL menos utilizadas después de las columnas que aceptan valores NULL utilizadas con más frecuencia

Un ejemplo de diferencia en el rendimiento es una búsqueda de índice. El motor de la base de datos encuentra una fila en función de algunas condiciones del índice y obtiene una dirección de fila. Ahora digamos que está buscando SomeValue, y está en esta tabla:

 SomeId int,
 SomeString varchar(100),
 SomeValue int

El motor tiene que adivinar dónde comienza SomeValue, porque SomeString tiene una longitud desconocida. Sin embargo, si cambia el orden a:

 SomeId int,
 SomeValue int,
 SomeString varchar(100)

Ahora el motor sabe que SomeValue se puede encontrar 4 bytes después del inicio de la fila. Por tanto, el orden de las columnas puede tener un impacto considerable en el rendimiento.

EDITAR: Sql Server 2005 almacena campos de longitud fija al comienzo de la fila. Y cada fila tiene una referencia al inicio de un varchar. Esto niega por completo el efecto que he enumerado anteriormente. Entonces, para las bases de datos recientes, el orden de las columnas ya no tiene ningún impacto.

Andomar
fuente
4
@TopBanana: no con varchars, eso es lo que los diferencia de las columnas char normales.
Allain Lalonde
1
No creo que el orden de las columnas EN LA TABLA haga ninguna diferencia; definitivamente hace una diferencia en los ÍNDICES que podrías crear, cierto.
marc_s
4
@TopBanana: no estoy seguro de si conoce Oracle o no, pero no reserva 100 bytes para un VARCHAR2 (100)
Quassnoi
1
@Quassnoi: el mayor impacto fue en Sql Server, en una tabla con muchas columnas varchar () anulables.
Andomar
7
La URL en esta respuesta ya no funciona, ¿alguien tiene una alternativa?
scunliffe
41

Actualizar:

En MySQL, puede haber una razón para hacer esto.

Dado que los tipos de datos variables (como VARCHAR) se almacenan con longitudes variables en InnoDB, el motor de la base de datos debe recorrer todas las columnas anteriores en cada fila para averiguar el desplazamiento de la dada.

El impacto puede llegar al 17% para las 20columnas.

Vea esta entrada en mi blog para más detalles:

En Oracle, las NULLcolumnas finales no consumen espacio, por eso siempre debe ponerlas al final de la tabla.

También en Oracley en SQL Server, en caso de una fila grande, ROW CHAININGpuede ocurrir un.

ROW CHANING es dividir una fila que no encaja en un bloque y extenderla por varios bloques, conectados con una lista vinculada.

La lectura de las columnas finales que no encajan en el primer bloque requerirá recorrer la lista vinculada, lo que resultará en una I/Ooperación adicional .

Consulte esta página para ver una ilustración de ROW CHAININGen Oracle:

Es por eso que debe colocar las columnas que usa a menudo al principio de la tabla y las columnas que no usa a menudo, o las columnas que tienden a serlo NULL, al final de la tabla.

Nota IMPORTANTE:

Si le gusta esta respuesta y desea votar a favor, vote también a favor de @Andomarla respuesta .

Él respondió lo mismo, pero parece haber sido rechazado sin ningún motivo.

Quassnoi
fuente
1
Entonces está diciendo que esto sería lento: seleccione tinyTable.id, tblBIG.firstColumn, tblBIG.lastColumn from tinyTable inner join tblBIG en tinyTable.id = tblBIG.fkID Si los registros tblBIG superan los 8KB (en cuyo caso se produciría un encadenamiento de filas ) y la unión sería sincrónica ... Pero esto sería rápido: seleccione tinyTable.id, tblBIG.firstColumn de tinyTable inner join tblBIG en tinyTable.id = tblBIG.fkID Ya que no usaría la columna en otros bloques, por lo tanto, no Necesito recorrer la lista vinculada. ¿Hice esto bien?
jfrobishow
1
Solo obtengo un 6%, y eso es para col1 frente a cualquier otra columna.
Rick James
6

Durante la capacitación de Oracle en un trabajo anterior, nuestro DBA sugirió que poner todas las columnas que no aceptan valores NULL antes de las que aceptan valores NULL era ventajoso ... aunque TBH, no recuerdo los detalles de por qué. ¿O tal vez solo los que probablemente se actualizarían deberían ir al final? (Quizás posponga tener que mover la fila si se expande)

En general, no debería haber ninguna diferencia. Como dice, las consultas siempre deben especificar las columnas en sí mismas en lugar de depender del orden de "seleccionar *". No conozco ninguna base de datos que permita cambiarlos ... bueno, no sabía que MySQL lo permitía hasta que lo mencionaste.

arácnido
fuente
4
Tenía razón, Oracle no escribe columnas NULL finales en el disco, lo que ahorra algunos bytes. Ver dba-oracle.com/oracle_tips_ault_nulls_values.htm
Andomar
absolutamente, puede marcar una gran diferencia en el tamaño en el disco
Alex
¿Es ese el vínculo al que te refieres? Está relacionado con la no indexación de nulos en índices en lugar de con el orden de las columnas.
araqnid
Enlace incorrecto y no puedo encontrar el original. Aunque puede buscarlo en
Andomar
5

Algunas aplicaciones mal escritas pueden depender del orden / índice de columna en lugar del nombre de columna. No deberían serlo, pero sucede. Cambiar el orden de las columnas rompería tales aplicaciones.

Craig Walker
fuente
3
Los desarrolladores de aplicaciones que hacen que su código dependa del orden de las columnas en una tabla MERECEN que sus aplicaciones se rompan. Pero los usuarios de la aplicación no merecen la interrupción.
spencer7593
4

Legibilidad de la salida cuando tiene que escribir:

select * from <table>

en su software de gestión de bases de datos?

Es una razón muy falsa, pero por el momento no puedo pensar en otra cosa.

ChrisF
fuente
4

No, el orden de las columnas en una tabla de base de datos SQL es totalmente irrelevante, excepto para fines de visualización / impresión. No tiene sentido reordenar las columnas; la mayoría de los sistemas ni siquiera proporcionan una forma de hacerlo (excepto eliminar la tabla anterior y volver a crearla con el nuevo orden de las columnas).

Bagazo

EDITAR: de la entrada de Wikipedia en la base de datos relacional, aquí está la parte relevante que, para mí, muestra claramente que el orden de las columnas nunca debería ser motivo de preocupación:

Una relación se define como un conjunto de n-tuplas. Tanto en matemáticas como en el modelo de base de datos relacional, un conjunto es una colección desordenada de elementos, aunque algunos DBMS imponen un orden a sus datos. En matemáticas, una tupla tiene un orden y permite la duplicación. EF Codd originalmente definió tuplas usando esta definición matemática. Más tarde, una de las grandes ideas de EF Codd fue que usar nombres de atributos en lugar de un orden sería mucho más conveniente (en general) en un lenguaje informático basado en relaciones. Esta información todavía se utiliza hoy.

marc_s
fuente
1
He visto que la diferencia de columnas tiene un gran impacto con mis propios ojos, así que no puedo creer que esta sea la respuesta correcta. Aunque la votación lo ponga primero. Hrm.
Andomar
¿En qué entorno SQL estaría eso?
marc_s
1
El mayor impacto que he visto fue en Sql Server 2000, donde mover una clave externa hacia adelante aceleró algunas consultas de 2 a 3 veces. Esas consultas tenían escaneos de tablas grandes (1M + filas) con una condición en la clave externa.
Andomar
5
Los RDBMS no dependen del orden de la mesa a menos que se preocupe por el rendimiento . Las diferentes implementaciones tendrán diferentes penalizaciones de rendimiento para el orden de las columnas. Puede ser enorme o minúsculo, depende de la implementación. Las tuplas son teóricas, los RDBMS son prácticos.
Esteban Küber
3
-1. Todas las bases de datos relacionales que he usado TIENEN orden de columnas en algún nivel. Si selecciona * de una tabla, no tiende a obtener columnas en orden aleatorio. Ahora en disco vs pantalla es un debate diferente. Y citar la teoría matemática para respaldar una suposición sobre implementaciones prácticas de bases de datos es una tontería.
DougW
2

La única razón en la que puedo pensar es para depurar y combatir incendios. Tenemos una tabla cuya columna "nombre" aparece aproximadamente en el décimo lugar de la lista. Es un fastidio cuando hace una selección rápida * de la tabla donde id en (1,2,3) y luego tiene que desplazarse para ver los nombres.

Pero eso es todo.

Chris Simpson
fuente
1

Como suele ser el caso, el factor más importante es el siguiente que tiene que trabajar en el sistema. Intento tener las columnas de clave primaria primero, las columnas de clave externa en segundo lugar y luego el resto de las columnas en orden descendente de importancia / significado para el sistema.

James L
fuente
Por lo general, comenzamos con la última columna "creada" (marca de tiempo para cuando se inserta la fila). Con tablas más antiguas, por supuesto, se pueden agregar varias columnas después de eso ... Y tenemos la tabla ocasional en la que una clave primaria compuesta se cambió a una clave sustituta, por lo que la clave primaria está varias columnas encima.
araqnid
1

Si va a utilizar mucho UNION, facilitará la comparación de columnas si tiene una convención sobre su ordenación.

Allain Lalonde
fuente
¡Parece que tu base de datos necesita normalizarse! :)
James L
¡Oye! Retirarlo, no dije mi base de datos. :)
Allain Lalonde
Hay razones lícitas para usar UNION;) Ver postgresql.org/docs/current/static/ddl-partitioning.html y stackoverflow.com/questions/863867/…
Esteban Küber
¿Puede UNION con el orden de las columnas en 2 tablas en orden diferente?
Monica Heddneck
Sí, solo necesita especificar las columnas explícitamente al consultar las tablas. Con las tablas A [a, b] B [b, a], eso significa (SELECT aa, ab FROM A) UNION (SELECT ba, bb FROM B) en lugar de (SELECT * FROM A) UNION (SELECT * FROM B).
Allain Lalonde
1

Como se señaló, existen numerosos problemas potenciales de rendimiento. Una vez trabajé en una base de datos en la que poner columnas muy grandes al final mejoraba el rendimiento si no hacía referencia a esas columnas en su consulta. Aparentemente, si un registro abarcaba varios bloques de disco, el motor de la base de datos podría dejar de leer bloques una vez que obtuviera todas las columnas que necesitaba.

Por supuesto, cualquier implicación en el rendimiento depende en gran medida no solo del fabricante que esté utilizando, sino también potencialmente de la versión. Hace unos meses noté que nuestro Postgres no podía usar un índice para una comparación de "me gusta". Es decir, si escribió "alguna columna como 'M%'", no fue lo suficientemente inteligente como para saltar a las M y salir cuando encontró la primera N. Estaba planeando cambiar un montón de consultas para usar "entre". Luego obtuvimos una nueva versión de Postgres y manejó los similares de manera inteligente. Me alegro de no haber podido cambiar las consultas. Obviamente no es directamente relevante aquí, pero mi punto es que cualquier cosa que haga por consideraciones de eficiencia podría quedar obsoleta con la próxima versión.

El orden de las columnas es casi siempre muy relevante para mí porque escribo rutinariamente código genérico que lee el esquema de la base de datos para crear pantallas. Por ejemplo, mis pantallas de "editar un registro" casi siempre se construyen leyendo el esquema para obtener la lista de campos y luego mostrándolos en orden. Si cambiara el orden de las columnas, mi programa seguiría funcionando, pero la visualización podría resultar extraña para el usuario. Por ejemplo, espera ver nombre / dirección / ciudad / estado / código postal, no ciudad / dirección / código postal / nombre / estado. Claro, podría poner el orden de visualización de las columnas en código o en un archivo de control o algo así, pero cada vez que agregamos o elimináramos una columna, tendríamos que recordar actualizar el archivo de control. Me gusta decir las cosas una vez. Además, cuando la pantalla de edición se crea exclusivamente a partir del esquema, agregar una nueva tabla puede significar escribir cero líneas de código para crear una pantalla de edición, lo cual es genial. (Bueno, está bien, en la práctica, por lo general, tengo que agregar una entrada al menú para llamar al programa de edición genérico, y generalmente he renunciado al genérico "seleccione un registro para actualizar" porque hay demasiadas excepciones para que sea práctico .)

Arrendajo
fuente
1

Más allá del ajuste de rendimiento obvio, me encontré con un caso de esquina en el que reordenar las columnas causaba que fallara un script SQL (anteriormente funcional).

De la documentación "Las columnas TIMESTAMP y DATETIME no tienen propiedades automáticas a menos que se especifiquen explícitamente, con esta excepción: de forma predeterminada, la primera columna TIMESTAMP tiene DEFAULT CURRENT_TIMESTAMP y ON UPDATE CURRENT_TIMESTAMP si ninguna de las dos se especifica explícitamente" https: //dev.mysql .com / doc / refman / 5.6 / en / timestamp-initialization.html

Entonces, un comando ALTER TABLE table_name MODIFY field_name timestamp(6) NOT NULL;funcionará si ese campo es la primera marca de tiempo (o fecha y hora) en una tabla, pero no de otra manera.

Obviamente, puede corregir ese comando alter para incluir un valor predeterminado, pero el hecho de que una consulta que funcionó dejó de funcionar debido a un reordenamiento de columna hizo que me doliera la cabeza.

slacker525600
fuente
0

La única vez que deberá preocuparse por el orden de las columnas es si su software se basa específicamente en ese orden. Por lo general, esto se debe al hecho de que el desarrollador se volvió vago e hizo un select *y luego se refirió a las columnas por índice en lugar de por nombre en su resultado.

Soviut
fuente
0

En general, lo que sucede en SQL Server cuando cambia el orden de las columnas a través de Management Studio es que crea una tabla temporal con la nueva estructura, mueve los datos a esa estructura desde la tabla anterior, elimina la tabla anterior y cambia el nombre de la nueva. Como puede imaginar, esta es una opción muy pobre para el rendimiento si tiene una mesa grande. No sé si Mi SQL hace lo mismo, pero es una de las razones por las que muchos de nosotros evitamos reordenar las columnas. Dado que select * nunca debe usarse en un sistema de producción, agregar columnas al final no es un problema para un sistema bien diseñado. Por lo general, no se debe alterar el orden de las columnas de la tabla.

HLGEM
fuente
0

En 2002, Bill Thorsteinson publicó en los foros de Hewlett Packard sus sugerencias para optimizar las consultas de MySQL reordenando las columnas. Desde entonces, su publicación ha sido literalmente copiada y pegada al menos un centenar de veces en Internet, a menudo sin citación. Para citarlo exactamente ...

Reglas generales:

  • Primero las columnas de clave primaria.
  • A continuación, columnas de clave externa.
  • A continuación, las columnas más buscadas.
  • Columnas que se actualizan con frecuencia más adelante.
  • Las columnas que aceptan valores NULL son las últimas.
  • Columnas que aceptan valores NULL menos utilizadas después de columnas que aceptan valores NULL utilizadas con más frecuencia.
  • Blobs en su propia tabla con algunas otras columnas.

Fuente: Foros de HP.

¡Pero esa publicación fue hecha en 2002! Este consejo fue para MySQL versión 3.23, más de seis años antes de que se lanzara MySQL 5.1. Y no hay referencias ni citas. Entonces, ¿Bill tenía razón? ¿Y cómo funciona exactamente el motor de almacenamiento a este nivel?

  1. Sí, Bill tenía razón.
  2. Todo se reduce a una cuestión de filas encadenadas y bloques de memoria.

Para citar a Martin Zahn, un profesional certificado por Oracle , en un artículo sobre Los secretos de la migración y encadenamiento de filas de Oracle ...

Las filas encadenadas nos afectan de manera diferente. Aquí, depende de los datos que necesitemos. Si tuviéramos una fila con dos columnas distribuidas en dos bloques, la consulta:

SELECT column1 FROM table

donde column1 está en el Bloque 1, no causaría ninguna «fila de búsqueda de tabla continua». En realidad, no tendría que obtener la columna 2, no seguiría la fila encadenada hasta el final. Por otro lado, si pedimos:

SELECT column2 FROM table

y la columna2 está en el Bloque 2 debido al encadenamiento de filas, entonces, de hecho, vería una «tabla buscar fila continua»

¡El resto del artículo es una lectura bastante buena! Pero solo estoy citando la parte que es directamente relevante para nuestra pregunta que nos ocupa.

Más de 18 años después, tengo que decirlo: ¡gracias, Bill!

Asignación de una fila de MySQL a un bloque de datos

HoldOffHunger
fuente