Tabla SQL dedicada que contiene solo cadenas únicas

Parece que no puedo encontrar ningún ejemplo de alguien que haga esto en la web, así que me pregunto si tal vez haya una razón para eso (o tal vez no he usado los términos de búsqueda correctos). ¿Incluso podría haber un término para esto que desconozco?

Para ahorrar espacio de almacenamiento en la base de datos para cadenas recurrentes, estoy pensando en crear una tabla MySQL llamada cadena_única. Solo tendría dos columnas:

  1. "identificación" : INT : índice PRIMARY_KEY
  2. "cuerda" : varchar(255) : índice ÚNICO

Cualquier otra tabla en cualquier lugar de la base de datos puede usar columnas INT en lugar de columnas VARCHAR. Por ejemplo, un campo varchar llamado cada navegador sería en cambio un campo INT llamado browser_unique_string_id.

No usaría esto para nada donde el rendimiento importe. En este caso, lo estoy usando para rastrear los detalles de cada solicitud de una sola página (registro de estadísticas web) y una "prueba de auditoría" de las acciones de los usuarios en las intranets, pero potencialmente también otras cosas.

También soy consciente de que las consultas SELECT serían complejas, por lo que no me preocupa eso. Lo más probable es que escriba algún código para generar las consultas para devolver los datos de cadena "reales".

¿Pensamientos? Siento que podría estar pasando por alto algo obvio aquí.

¡Gracias!

preguntado el 22 de mayo de 12 a las 14:05

Puede que me esté perdiendo lo que buscas hacer, pero lo que estás describiendo suena exactamente como la mejor práctica de normalización de la base de datos Vanilla; stackoverflow.com/questions/723998/… -

¿Normalización? - "La normalización de bases de datos es el proceso de organizar los campos y tablas de una base de datos relacional para minimizar la redundancia y dependencia." - De Wikipedia -

lo que entiendo es que desea almacenar el varchar en una tabla con una identificación, y va a trabajar con la identificación en lugar del tipo varchar, ¿verdad? -

Sí, supongo que la razón por la que pregunto es que no he visto ningún ejemplo de tener una tabla principal de cadenas a la que se haga referencia en toda la base de datos para absolutamente cualquier cosa que sea una cadena. En general, habrá varias tablas que son específicamente una lista de "algo", como una tabla de títulos de trabajo. -

Puede que le interese el motor de almacenamiento ARCHIVE - dev.mysql.com/doc/refman/5.5/en/archive-storage-engine.html - comprime datos y apuesto a que zlib hará un trabajo bastante bueno en comparación con lo que podría hacer en la compresión WRT de consultas SQL. -

3 Respuestas

He usado esta estructura para una aplicación similar: realizar un seguimiento de los URI para los registros web. En este caso, la base de datos era Oracle.

Los problemas de rendimiento no son mínimos. A medida que crece la base de datos, hay decenas de millones de URI. Entonces, solo identificar la cadena correcta durante un INSERTAR es un desafío. Manejamos esto construyendo la mayor parte de la lógica de actualización en hadoop, por lo que la tabla de la base de datos era, en esencia, solo una copia de una tabla de hadoop.

En una base de datos regular, solucionaría esto creando un índice, como sugiere en su pregunta. Y, una solución de índice funcionaría bien hasta su memoria disponible. De hecho, este es un caso bastante degenerado para un índice, porque realmente solo necesita el índice y no la tabla subyacente. No sé si mysql o SQL Server reconocen esto, aunque las bases de datos en columnas (como Vertica) deberían hacerlo.

SQL Server tiene otra opción. Si declara la cadena como VARCHAR(max), entonces no se almacena en una página de datos separada del resto de los datos. Durante una exploración completa de la tabla, no es necesario cargar la página adicional en la memoria, si no se hace referencia a la columna en la consulta.

contestado el 22 de mayo de 12 a las 15:05

Gracias, sí, un punto interesante sobre las cosas que van mal cuando el índice aumenta. Para este proyecto, creo que debería estar bien, ya que solo hay unas 10 URL y un conjunto limitado de navegadores, etc. Solo lo usaré para cadenas recurrentes. - LaVache

Este es un patrón de diseño muy común en las bases de datos donde la cardinalidad de los datos es relativamente pequeña en comparación con la tabla de transacciones a la que están vinculados. Las consultas no serían muy complejas, solo una simple unión a la tabla de búsqueda. Puede incluir más que solo una cadena en la tabla de búsqueda, otra información que se repite comúnmente. eres simplemente normalizadora su modelo para eliminar datos duplicados.

Ejemplo:

Solicite Mesa:

Date    
Time   
IP Address    
Browser_ID  

Navegador Mesa:

Browser_ID
Browser_Name
Browser_Version
Browser_Properties

contestado el 22 de mayo de 12 a las 15:05

Gracias por su respuesta. Creo que podría haber sido más específico con mi pregunta. Estoy preguntando más acerca de tener una tabla maestra de cadenas para cualquier tipo de datos, que se use en toda la base de datos en lugar de tener varias tablas de cadenas para entidades específicas. - LaVache

Reemplazar texto con un número de identificación no tiene nada que ver con la normalización. Y no está eliminando datos duplicados; está reemplazando texto repetido con números repetidos. - Mike Sherrill 'Cat Recall'

Si tiene "Nombre del navegador, Versión del navegador" en su tabla principal y la reemplaza con una clave externa en la tabla principal con una relación de 1-M con la tabla "Navegador", ha eliminado los datos duplicados del sistema de archivos y los ha reemplazado. con una llave. Llaves extranjeras son una parte esencial de la normalización. en.wikipedia.org/wiki/Foreign_key - N Oeste

Si planea registrar datos en tiempo real (a diferencia de un trabajo por lotes), entonces quiere asegurarse de que su tiempo para escribir un registro en la base de datos sea lo más rápido posible. Si está iniciando sesión sincrónicamente, obviamente, el tiempo de creación del registro afectará directamente el tiempo que tarda en completarse una solicitud http. Si esto es asíncrono, los tiempos lentos de creación de registros conducirán a un cuello de botella. Sin embargo, si se trata de un trabajo por lotes, el rendimiento no importará siempre que pueda crear con confianza todos los registros por lotes antes de que se ejecute el siguiente lote.

Para reducir el tiempo que lleva crear un registro, realmente desea aplanar la estructura de su base de datos, su consulta actual en pseudo podría verse así

SELECT @id = id from PagesTable
WHERE PageName = @RequestedPageName

IF @id = 0
THEN 
  INSERT @RequestedPageName into PagesTable
  @id = SELECT @@IDENTITY 'or whatever method you db supports for              
                          'fetching the id for a newly created record
END IF

INSERT @id, @BrowserName INTO BrowersLogTable 

Donde, como en una estructura plana, solo necesitaría 1 INSERCIÓN

Si está preocupado por la integridad de los datos, lo que debería estarlo, normalmente normalizaría estos datos al consultarlos escribiéndolos en un conjunto separado de tablas (o una base de datos separada) a intervalos regulares y usar esto para realizar consultas.

contestado el 22 de mayo de 12 a las 15:05

Genial gracias. Este es exactamente el tipo de cosas en las que no había pensado (el rendimiento durante la creación de registros). En mi caso debería estar bien. Independientemente de la cantidad de campos "unique_string" en cualquier tabla, puedo extraer todas las ID con una consulta SELECCIONAR inicial antes de INSERTAR (suponiendo que los valores ya se hayan usado en el pasado, que será la mayoría). Si mi sitio alguna vez está lo suficientemente ocupado como para ralentizar las cosas, sería un gran problema. =) - LaVache

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.