2009-10-27 16 views
8

¿Cómo se manejan internamente las columnas varchar mediante un motor de base de datos? Para una columna definida como char (100), el DBMS asigna 100 bytes contiguos en el disco. Sin embargo, para una columna definida como varchar (100), presumiblemente no es el caso, ya que el punto total de varchar es no asignar más espacio que el requerido para almacenar el valor real de los datos almacenados en la columna. Entonces, cuando un usuario actualiza una fila de base de datos que contiene una columna varchar (100) vacía a un valor que consta de 80 caracteres, por ejemplo, ¿de dónde se asigna el espacio para esos 80 caracteres? Parece que las columnas varchar deben dar lugar a una buena cantidad de fragmentación de las filas reales de la base de datos, al menos en escenarios donde los valores de las columnas se insertan inicialmente como en blanco o NULL, y luego se actualizan con valores reales. ¿Esta fragmentación da como resultado un rendimiento degradado en las consultas de la base de datos, en lugar de usar valores de tipo de caracteres, donde el espacio para las columnas almacenadas en las filas se asigna contiguamente? Obviamente, usar varchar da como resultado menos espacio en disco que utilizar char, pero ¿hay un impacto en el rendimiento al optimizar el rendimiento de las consultas, especialmente para las columnas cuyos valores se actualizan frecuentemente después de la inserción inicial?¿Varchar da como resultado un golpe de rendimiento debido a la fragmentación de datos?

Respuesta

4

Las estructuras de datos utilizadas dentro de un motor de base de datos son mucho más complejas que usted le dan crédito! Sí, hay problemas de fragmentación y problemas donde actualizar un varchar con un gran valor puede causar un golpe de rendimiento, sin embargo, es difícil explicar/entender cuáles son las implicaciones de esos problemas sin una comprensión más completa de las estructuras de datos involucrado.

Para el servidor MS SQL, es posible que desee comenzar con la comprensión de páginas - la unidad fundamental de almacenamiento (ver http://msdn.microsoft.com/en-us/library/ms190969.aspx)

En cuanto a las implicaciones de rendimiento de correcciones vs tipos de almacenamiento variable sobre el rendimiento hay una serie de puntos a tener en cuenta:

  • el uso de columnas de longitud variable puede mejorar el rendimiento, ya que permite más filas que caben en una sola página, lo que significa menos lee
  • el uso de columnas de longitud variable requiere especial los valores de desplazamiento, y el mantenimiento de estos valores requiere s una ligera sobrecarga, sin embargo, esta sobrecarga adicional es generalmente insignificante.
  • Otro costo potencial es el costo de aumentar el tamaño de una columna cuando la página que contiene esa fila está casi llena

Como se puede ver, la situación es bastante compleja - hablando en términos generales, sin embargo se puede confiar en la base de datos el motor es bastante bueno para tratar con tipos de datos variables y debe ser el tipo de datos de elección cuando puede haber una variación significativa de la longitud de los datos contenidos en una columna.

En este punto, también voy a recomendar el excelente libro "Microsoft Sql Server 2008 Internals" para obtener más información sobre cuán complejas son las cosas como esta.

7

Se hacen muchas suposiciones en su pregunta que no son necesariamente cierto.

El tipo de una columna en cualquier DBMS te dice nada en absoluto acerca de la naturaleza del almacenamiento de los datos a menos que la documentación que dice claramente cómo se almacenan los datos. Si eso no se establece, no se sabe cómo se almacena y el DBMS puede cambiar el mecanismo de almacenamiento de versión a versión.

De hecho algunos campos CHAR almacenar bases de datos internamente como VARCHAR, mientras que otros tomar una decisión sobre la forma de la tienda de la columna en función del tamaño declarado de la columna. Algunas bases de datos almacenan VARCHAR con las otras columnas, algunas con datos BLOB y otras implementan otro almacenamiento. Algunas bases de datos siempre reescriben toda la fila cuando se actualiza una columna, otras no. Algunos rellenan VARCHAR para permitir actualizaciones futuras limitadas sin reubicar el almacenamiento.

El DBMS es responsable de encontrar la manera de almacenar los datos y volver a usted de una manera rápida y consistente. Siempre me sorprende cuántas personas prueben la base de datos, generalmente antes de detectar cualquier problema de rendimiento.

+0

+1: La pregunta también asume una cantidad significativa de actualización que expande los campos de VARCHAR. Incluso esto puede ser, en algunas aplicaciones, un porcentaje de filas infinitamente pequeño. –

+0

Gracias por las respuestas. Mi pregunta básica fue cómo el DBMS almacena datos de longitud variable, y las respuestas han arrojado luz sobre eso para mí. El DB en cuestión tiene un número de columnas algo grandes que inicialmente están en blanco en la inserción y se rellenaron más tarde, por lo que mi preocupación general era cómo manejarlo el DBMS, y posibles problemas de rendimiento debido a saltos alrededor del disco versus uso de caracteres. –

+0

@E. Depende completamente de su DBMS, y es posible que no puedan publicar esa información. Sin embargo, la mayoría de los DBMS modernos son conscientes de problemas como la fragmentación de datos e incluyen optimizaciones para evitar la pérdida de rendimiento. A menos que detecte un problema de rendimiento, permitiría que la base de datos lo maneje por usted.(Supongo, supongo que la mayoría de los DBMSes volverán a escribir la fila sobre el almacenamiento actual si corresponde, o en el nuevo almacenamiento si no lo hace, liberando el almacenamiento anterior, con más o menos el mismo rendimiento en cualquiera de los dos) caso). –

3

La respuesta dependerá de los DBMS específico. Para Oracle, sin duda es posible terminar con la fragmentación en forma de "filas encadenadas", y eso implica una penalización de rendimiento. Sin embargo, puede mitigarlo al asignar previamente espacio vacío en los bloques de la tabla para permitir alguna expansión debido a las actualizaciones. Sin embargo, las columnas CHAR generalmente harán que la tabla sea mucho más grande, lo que tiene su propio impacto en el rendimiento. CHAR también tiene otros problemas, como las comparaciones en blanco, lo que significa que, en Oracle, el uso del tipo de datos CHAR es casi nunca una buena idea.

2

su pregunta es demasiado general porque los diferentes motores de bases de datos tendrán un comportamiento diferente. Si realmente necesita saber esto, le sugiero que configure un punto de referencia para escribir una gran cantidad de registros y cronometrarlos. Querrías suficientes registros para tomar al menos una hora para escribir.

Como sugirió, sería interesante ver qué pasa si escribe insertar todos los registros con una cadena vacía ("") y luego actualizarlos para tener 100 caracteres que son razonablemente aleatorios, no solo 100 Xs.

Si prueba esto con SQLITE y no ve una diferencia significativa, entonces creo que es poco probable que los servidores de bases de datos más grandes, con todos los análisis y sintonizaciones, sean peores que SQLITE.

+0

SQLite es un ejemplo perfecto de lo que estaba diciendo en mi comentario anterior sobre no conocer el mecanismo de almacenamiento de datos. Debajo del capó, SQLite ni siquiera HAYA escrito el almacenamiento: puede insertar datos similares a VARCHAR en cualquier tipo de columna (incluso INTEGER). –

+0

La pregunta es, ¿esto marca alguna diferencia en el rendimiento? Solo una prueba dirá con certeza. Por un lado, los desarrolladores de software pueden haberse dado cuenta del potencial de fragmentación y mitigarlo de alguna manera. Por otro lado, el relleno adicional de caracteres de longitud fija probablemente provocará más E/S de archivos, pero también puede mitigarse. Debe comparar las variaciones para saber si hay una diferencia significativa. –

1

En SQL Server varchar (excepto varchar (MAX)) generalmente se almacena junto con el resto de los datos de la fila (en la misma página si los datos de la fila son < 8 KB y en la misma medida si es < 64 KB. los tipos de datos grandes como TEXTO, NTEXT, IMAGEN, VARHCAR (MAX), NVARHCAR (MAX), XML y VARBINARIO (MAX) se almacenan por separado

2

Esto va a ser completamente específico de la base de datos.

Sé que en Oracle, la base de datos reservará un cierto porcentaje de cada bloque para futuras actualizaciones (el parámetro PCTFREE). Por ejemplo, si PCTFREE se establece en 25%, entonces un bloque solo se usará para nuevos datos hasta que esté lleno al 75%. Al hacer eso, queda espacio para que las filas crezcan. Si la fila crece de manera que el 25% del espacio reservado se agote por completo, terminará con filas encadenadas y una penalización de rendimiento. Si encuentra que una tabla tiene una gran cantidad de filas encadenadas, puede sintonizar PCTFREE para esa tabla. Si tiene una tabla que nunca tendrá ninguna actualización, una PCTFREE de cero tendría sentido

Cuestiones relacionadas