un índice con todas las llaves cerca de 900 bytes haría ser muy grande y muy profundo (muy pocas teclas por página resultan en B-Trees muy altos).
Depende de cómo va a consultar los valores. Un índice es útil en varios casos:
- cuando se prueba un valor. Este es el uso más típico, es cuando se busca un valor exacto en la tabla. Los ejemplos típicos son
WHERE column='ABC'
o una condición de unión ON a.column = B.someothercolumn
.
- cuando se escanea un rango. Esto también es bastante típico cuando se busca en la tabla rango de valores. Además del ejemplo obvio de
WHERE column BETWEEN 'ABC' AND 'DEF'
, hay otros ejemplos menos obvios, como una coincidencia parcial: WHERE column LIKE 'ABC%'
.
- un requisito de pedido. Este uso es menos conocido, pero los índices pueden ayudar a una consulta que tiene un requisito explícito de
ORDER BY column
para evitar una orden stop-and-go, y también puede ayudar a ciertos requisitos de clasificación ocultos, como un ROW_NUMBER() OVER (ORDER BY column)
.
Entonces, ¿por qué necesita el índice? ¿Qué tipo de consultas usaría?
Para los escaneos de rango y para los requisitos de pedido, no hay otra solución más que tener el índice, y tendrá que ponderar el costo del índice frente a los beneficios.
Para las sondas, puede, potencialmente, usar hash para evitar indexar una columna muy grande. Cree una columna calculada persistente como column_checksum = CHECKSUM(column)
y luego indexe en esa columna. Las consultas deben reescribirse para usar WHERE column_checksum = CHECKSUM('ABC') AND column='ABC'
. Se debe considerar cuidadosamente la posibilidad de ponderar la ventaja de un índice estrecho (suma de comprobación de 32 bits) frente a las desventajas de la doble verificación de colisión y la falta de escaneo de rango y capacidades de orden.
después del comentario
Una vez tuve un problema similar y utilicé una columna de hash. El valor era demasiado grande para indexar (> 1K) y también necesitaba convertir el valor en una ID para almacenar (básicamente, un diccionario). Algo a lo largo de las líneas:
create table values_dictionary (
id int not null identity(1,1),
value varchar(8000) not null,
value_hash = checksum(value) persisted,
constraint pk_values_dictionary_id
primary key nonclustered (id));
create unique clustered index cdx_values_dictionary_checksum on (value_hash, id);
go
create procedure usp_get_or_create_value_id (
@value varchar(8000),
@id int output)
begin
declare @hash = CHECKSUM(@value);
set @id = NULL;
select @id = id
from table
where value_hash = @hash
and value = @value;
if @id is null
begin
insert into values_dictionary (value)
values (@value);
set @id = scope_identity();
end
end
En este caso, la tabla de diccionario se organiza como un índice agrupado en la columna de la values_hash
que agrupa a todos los valores de hash que chocan juntos. La columna id
se agrega para hacer que el índice agrupado sea único, evitando la necesidad de un hidden uniqueifier column. Esta estructura hace que la búsqueda de @value
sea lo más eficiente posible, sin un índice enormemente ineficiente en value
y eludiendo la limitación de 900 caracteres. La clave principal en id
no está agrupada, lo que significa que al buscar value
y id
se incurre en la sobrecarga de una sonda adicional en el índice agrupado.
No estoy seguro si esto responde su problema, obviamente sabe más sobre sus escenarios reales que yo. Además, el código no maneja las condiciones de error y puede insertar entradas @value duplicadas, que pueden ser correctas o no.
Su pregunta no es particularmente útil sin contexto. ¿Por qué crees que necesitas un índice? Cómo lo usarías? – Anon246
ver comentario abajo Remus Rusanu – Ghita
Alguien sabe si sería útil usar https://msdn.microsoft.com/en-us/library/ms174415.aspx si debe usar cadenas largas para este tipo de cosas. – HumbleWebDev