SQL SELECT velocidad int vs varchar

110

Estoy en el proceso de crear una mesa y me hizo preguntarme.

Si almaceno, digamos automóviles que tienen una marca (fx BMW, Audi, etc.), ¿habrá alguna diferencia en la velocidad de consulta si almaceno la marca como int o varchar?

Asi es

SELECT * FROM table WHERE make = 5 AND ...;

Más rápido / más lento que

SELECT * FROM table WHERE make = 'audi' AND ...;

o la velocidad será más o menos la misma?

googletorp
fuente

Respuestas:

99

Las comparaciones de int son más rápidas que las comparaciones de varchar, por el simple hecho de que los ints ocupan mucho menos espacio que los varchars.

Esto es válido tanto para el acceso indexado como para el no indexado. La forma más rápida de hacerlo es una columna int indexada.


Como veo que ha etiquetado la pregunta postgreql, es posible que le interese el uso del espacio de diferentes tipos de fechas:

Robert Munteanu
fuente
13
Se refiere a la página 7.4. En las versiones modernas, ocupan más de 1 byte de longitud si tiene <126 bytes. También tenga en cuenta que la razón por la que las cadenas son mucho más lentas es a menudo que la comparación sensible a la intercalación es enormemente cara, no porque la cadena ocupe más espacio. Pero el resultado final es el mismo, por supuesto.
Magnus Hagander
@Magnus: gracias por el aviso. Siéntase libre de editar mi respuesta, ya que veo que tiene suficientes puntos de repetición.
Robert Munteanu
"no es que la cadena ocupe más espacio" ... las cadenas de caracteres por encima de los tamaños mínimos ocupan mucho más espacio que incluso los números de alta precisión, porque un número (singular) tiene una unidad fija, las cadenas siempre son tipos agregados . 8 bytes para un número de 64 bits 4 bytes por carácter en una cadena, incluido un byte de longitud o una estructura; u otro personaje terminador para implementaciones increíblemente ingenuas ...
MrMesees
@RobertMunteanu Hola Robert, disculpas, sé que esta es una publicación antigua, pero puedo verificar amablemente ... lo siguiente: para consultar números enteros, tengo que vincular cada columna de cadena a otra tabla (relación). sin embargo, eso significa que se requieren más operaciones de unión para cada consulta. ¿Cómo puedo determinar si vale la pena esta compensación? ¡Gracias!
AiRiFiEd
2
"Las comparaciones de int son más rápidas que las comparaciones de varchar, por el simple hecho de que los ints ocupan mucho menos espacio que los varchars", esto NO es cierto en general . Dependiendo del DBMS que use y los tipos de datos exactos y las cadenas que desee insertar, puede resultar que sus (digamos) entradas de 8 bytes sean más largas que los varchars ascii que contienen algunas ID textuales de longitud promedio de 3 a 4 caracteres. Entonces, esta respuesta, que es imprecisa y carece de contexto específico o resultados experimentales, realmente no responde a la pregunta. Todo el mundo sabe que los varchars pueden ocupar mucho más espacio que los ints, pero NO es necesario.
Marcin Wojnarski
36

Algunos puntos de referencia aproximados:

4 millones de registros en Postgres 9.x

Table A = base table with some columns
Table B = Table A + extra column id of type bigint with random numbers
Table C = Table A + extra column id of type text with random 16-char ASCII strings

Resultados en portátiles de 8GB RAM, i7, SSD:

Size on disk:                A=261MB        B=292MB        C=322MB
Non-indexed by id: select count(*), select by id: 450ms same on all tables
Insert* one row per TX:       B=9ms/record        C=9ms/record
Bulk insert* in single TX:    B=140usec/record    C=180usec/record
Indexed by id, select by id:  B=about 200us       C=about 200us

* inserts to the table already containing 4M records

por lo que parece que para esta configuración, siempre que sus índices quepan en la RAM, el texto de bigint frente a 16 caracteres no hace ninguna diferencia en la velocidad.

Grzegorz Luczywo
fuente
6
Muy interesante. ¿Por qué la diferencia es insignificante?
Chibueze Opata
18

Será un poco más rápido usar un int en lugar de un varchar. Más importante para la velocidad es tener un índice en el campo que la consulta pueda usar para encontrar los registros.

Hay otra razón para usar un int, y es normalizar la base de datos. En lugar de tener el texto 'Mercedes-Benz' almacenado miles de veces en la tabla, debe almacenar su identificación y guardar el nombre de la marca una vez en una tabla separada.

Guffa
fuente
¿Podrías explicarme más? ¿Quiere decir en lugar de Mercedes-Benzalmacenar miles de veces id 1. Por ejemplo car_brands, tabla , columnas Brandsy Id. Fila Mercedes-Benzy 1. Y en la columna Brandsy valor de la tabla principal 1. Y cuando SELECT, luego primero salga Idde la mesa car_brandsy luego SELECT Something FROM main_table WHERE Brands = (SELECT Id FROM car_brands WHERE Brands = Mercedes-Benz). ¿O algún otro enfoque?
Andris
3
@ user2118559: Sí, así es como lo almacenarías. Para obtener los datos que utilizaría generalmente una unión en lugar de una subconsulta: select something from main_table c inner join car_brands b on b.Id = c.Brands where b.Brands = 'Mercedes-Benz'.
Guffa
¿Por qué el voto negativo? Si no explica qué es lo que cree que está mal, no puede mejorar la respuesta.
Guffa
8

Desglosando el rendimiento real de la comparación de cadenas frente a no flotantes, en este caso, cualquier tamaño sin firmar y firmado no importa. El tamaño es en realidad la verdadera diferencia en el rendimiento. Ya sea 1byte + (hasta 126bytes) versus comparación de 1, 2, 4 u 8 bytes ... obviamente, los no flotantes son más pequeños que las cadenas y los flotantes y, por lo tanto, más amigables con la CPU en ensamblaje.

La comparación de cadena a cadena en todos los idiomas es más lenta que algo que la CPU puede comparar en 1 instrucción. Incluso comparar 8 bytes (64 bits) en una CPU de 32 bits es aún más rápido que un VARCHAR (2) o más. * Nuevamente, mire el ensamblaje producido (incluso a mano), se necesitan más instrucciones para comparar char por char que numérico de CPU de 1 a 8 bytes.

Ahora, ¿cuánto más rápido? depende también del volumen de datos. Si simplemente está comparando 5 con 'audi', y eso es todo lo que tiene su base de datos, la diferencia resultante es tan mínima que nunca la verá. Dependiendo de la CPU, la implementación (cliente / servidor, web / script, etc.) probablemente no lo verá hasta que alcance unos cientos de comparaciones en el servidor de base de datos (tal vez incluso un par de miles de comparaciones antes de que se note).

  • Para anular la disputa incorrecta sobre las comparaciones hash. La mayoría de los algoritmos hash en sí mismos son lentos, por lo que no se beneficia de cosas como CRC64 y más pequeñas. Durante más de 12 años desarrollé algoritmos de búsqueda para motores de búsqueda de varios condados y 7 años para los burós de crédito. Cualquier cosa que pueda guardar en números más rápido ... por ejemplo, números de teléfono, códigos postales, incluso moneda * 1000 (almacenamiento) moneda div 1000 (recuperación) es más rápido que DECIMAL para las comparaciones.

Ozz

Ozz Nixon
fuente
6

Con índice o no, int es mucho más rápido (cuanto más largo es el varchar, más lento se vuelve).

Otra razón: el índice en el campo varchar será mucho más grande que en int. Para tablas más grandes, puede significar cientos de megabytes (y miles de páginas). Eso hace que el rendimiento sea mucho peor, ya que la lectura del índice solo requiere muchas lecturas de disco.

Konrad Garus
fuente
3
Por ejemplo, de 5 millones de registros de "audi", ¿no contendría el índice solo una copia de la cadena de "audi" y 5 millones de enteros de primary_key? ¿La diferencia de tamaño sería realmente tan grande, ya sea vchar o integer?
lulalala
Tienes razón, lulalala, pero para una columna que va a contener cadenas aleatorias, la respuesta es bastante justa.
Awais fiaz
4

En general, el int será más rápido. Cuanto más largo es el varchar, más lento se vuelve

anthares
fuente
3

Consejo: Si los valores posibles para el campo maquillaje serán nunca más (o rara vez) el cambio, puede utilizar ENUM como un compromiso. Combina buena velocidad con buena legibilidad.

Thomas Schaub
fuente
1
Interesante, ¿cómo será la diferencia de velocidad entre ENUM e int?
googletorp
¿PostgresSQL tiene un enumtipo de datos? Pensé que era específico de MySQL.
Robert Munteanu
Postgres tiene ENUM, pero no creo que esté implementado de la misma manera que MySQL. postgresql.org/docs/current/static/datatype-enum.html
googletorp
2
En cuanto al rendimiento, ENUM debería funcionar más o menos igual que int en el campo de búsqueda, pero como varchar en la lista de destino (porque tiene que transferir toda la cadena al cliente para las filas coincidentes, no solo el int)
Magnus Hagander
1
Aquí una lectura interesante sobre por qué NO usar enumeración en MySQL (solo para agregar algo de combustible al fuego: D)
Wilt
1

Si activa la indexación en cualquiera de los campos, será más rápido. En cuanto a tu pregunta, creo que intes más rápido que varchar.

Sarfraz
fuente
0

Algo relativo. Sí, los INT serán más rápidos, pero la pregunta es si se nota en su situación. ¿Son los VARCHAR solo algunas palabras pequeñas o textos más largos? y cuantas filas hay en la tabla? Si hay solo unas pocas filas, lo más probable es que esté completamente almacenado en memoria intermedia (cuando se solicite con frecuencia), en ese caso, no notará mucha diferencia. Luego, por supuesto, está la indexación, que se vuelve más importante cuando la tabla crece. Usar SSD puede ser más rápido que HD con consultas optimizadas. Además, los buenos controladores de disco a veces aceleran las consultas> 10 veces. Esto podría dejar espacio para usar VARCHAR, lo que facilita la lectura y escritura de consultas (no es necesario escribir uniones complejas) y acelera el desarrollo. Sin embargo, los puristas no estarán de acuerdo y siempre normalizarán todo.

Alex
fuente