Estoy desarrollando una aplicación en Ruby on Rails con la base de datos PostgreSQL (9.4). Para mi caso de uso, las columnas en las tablas se buscarán con mucha frecuencia, ya que todo el punto de la aplicación busca atributos muy específicos en un modelo.
Actualmente estoy decidiendo si usar un integer
tipo o simplemente usar un tipo de cadena típico (por ejemplo character varying(255)
, que es el predeterminado en Rails ) para las columnas, ya que no estoy seguro de cuál será la diferencia de rendimiento en el índice.
Estas columnas son enumeraciones . Tienen un tamaño fijo para la cantidad de valores posibles que pueden tener. La mayoría de las longitudes de enumeración no exceden de 5, lo que significa que el índice estaría más o menos fijo durante la vida útil de la aplicación ; por lo tanto, los índices de enteros y cadenas serían idénticos en el número de nodos.
Sin embargo, la cadena que se indexaría podría tener alrededor de 20 caracteres, que en la memoria es aproximadamente 5 veces mayor que la del entero (si un entero es de 4 bytes, y las cadenas son ASCII puro a 1 byte por carácter, entonces esto se mantiene). No sé cómo los motores de base de datos realizan búsquedas de índice, pero si necesita "escanear" la cadena hasta que coincida exactamente , entonces, en esencia, eso significa que la búsqueda de cadena sería 5 veces más lenta que una búsqueda de enteros; el "escaneo" hasta la coincidencia para la búsqueda de enteros sería de 4 bytes en lugar de 20. Esto es lo que estoy imaginando:
El valor de búsqueda es (entero) 4:
escaneo ............................ ENCONTRADO | obtener registros ... | BYTE_1 | BYTE_2 | BYTE_3 | BYTE_4 | BYTE_5 | BYTE_6 | BYTE_7 | BYTE_8 | ... |
El valor de búsqueda es (cadena) "some_val" (8 bytes):
exploración................................................. .................................... ENCONTRADO | obtener registros ... | BYTE_1 | BYTE_2 | BYTE_3 | BYTE_4 | BYTE_5 | BYTE_6 | BYTE_7 | BYTE_8 | ... |
Espero que eso tenga sentido. Básicamente, debido a que el entero ocupa menos espacio, puede "emparejarse" más rápido que su contraparte de cadena. Tal vez esta es una suposición completamente equivocada, pero no soy un experto, ¡por eso les pregunto! Supongo que esta respuesta que acabo de encontrar parece apoyar mi hipótesis, pero quiero estar seguro.
El número de valores posibles en la columna no cambiaría al usar ninguno de los dos, por lo que el índice en sí no cambiaría (a menos que agregue un nuevo valor a la enumeración). En este caso, ¿habría alguna diferencia de rendimiento al usar integer
o varchar(255)
, o tiene más sentido usar un tipo entero?
La razón por la que pregunto es que el enum
tipo de Rails asigna enteros a las teclas de cadena, pero no están destinados a ser columnas orientadas al usuario. Básicamente, no puede verificar que el valor de enumeración sea válido, porque un valor no válido generará un ArgumentError
antes de que se puedan ejecutar las validaciones. El uso de un string
tipo permitiría validaciones, pero si hay un costo de rendimiento, prefiero simplemente solucionar el problema de validación.
varchar(255)
vs. ejvarchar(260)
. Es posible que haya habido algo así con SQL Server 6.x, pero esto no ha sido así durante mucho tiempo.