2009-11-11 11 views
18

Mi tabla (SQL Server 2008) tiene más de 1 millón de registros, cuando intento ordenar registros por fecha y hora, demora 1 segundo, pero cuando ordeno por ID (int), solo toma alrededor de 0.1 segundo.SQL Server 2008: ordenar por fecha y hora es demasiado lento

¿Hay alguna manera de mejorar la eficiencia? (Ya agregué la columna de fecha y hora en el índice)

+0

¿Qué 'RDBMS' estás usando? – Quassnoi

+0

Estoy usando SQL Server 2008 – silent

+7

¿Es esa columna de fecha y hora en un índice separado propio? Usted dice "agregado ... al índice" ....si la columna de fecha y hora es, p. columna no. 3 en un índice compuesto, eso no ayudará en absoluto al tratar de ordenar solo por esa columna de fecha y hora ........ –

Respuesta

23

Realizando su pedido por id probablemente utilice un análisis de índice agrupado mientras ordena por datetime utiliza la búsqueda de clasificación o de índice.

Ambos métodos son más lentos que un análisis de índice agrupado.

Si su tabla está agrupada por id, básicamente significa que ya está ordenada. Los registros están contenidos en un B+Tree que tiene una lista vinculada que vincula las páginas en el orden id. El motor solo debe atravesar la lista vinculada para obtener los registros ordenados por id.

Si se insertaron id s en orden secuencial, esto significa que el orden físico de las filas coincidirá con el orden lógico y el análisis de índice agrupado será aún más rápido.

Si desea que sus registros a ser ordenados por datetime, hay dos opciones:

  • tomar todas las fichas de la mesa y ordenarlos. La lentitud es obvia.
  • Utilice el índice en datetime. El índice se almacena en un espacio separado del disco, lo que significa que el motor debe desplazarse entre las páginas de índice y las páginas de la tabla en un bucle anidado. Es más lento también.

A fin de mejorar la ordenación, se puede crear un índice de cobertura separada sobre datetime:

CREATE INDEX ix_mytable_datetime ON mytable (datetime) INCLUDE (field1, field2, …) 

, e incluyen todas las columnas que utiliza en su consulta en ese índice.

Este índice es como una instantánea de su tabla pero con datos ordenados en orden diferente.

Esto le permitirá deshacerse de las búsquedas de claves (dado que el índice contiene todos los datos) lo que hará que el pedido sea datetime tan rápido como en id.

Actualización:

un blog fresco sobre este problema:

+0

¿Hay alguna manera eficiente de hacer esto? – silent

+0

Creo que la base de datos lo habrá almacenado en este formato de todos modos (y también lo compara de esta manera). También pensé lo mismo al principio, pero no creo que deba ser la respuesta. – Jrud

+1

+1 Para optimizar para la ordenación de fecha y hora, establezca la fecha y hora en el índice agrupado y el índice de Id. En una clave principal no agrupada. – Andomar

0

tal vez si almacena DataTime como int, pero se necesitaría mucho tiempo convirtiendo cada vez que se almacenar u obtener datos. (técnica común utilizada para personal de la tienda como la dirección IP y tienen unas buscar más rápido veces)

debe verificar en el servidor de cómo se almacena la fecha y hora, b/c su servidor ya se almacena como int o bigint .. lo hará no cambia nada ...

2

Agregue el tiempo de fecha a un nuevo índice, y al agregarlo a la identificación uno no ayudará mucho.

0

Si su campo de fecha y hora contiene muchos valores distintos y esos valores raramente cambian, defina un índice agrupado en el campo de fecha y hora, esto ordenará los datos reales por el valor de fecha y hora. Consulte http://msdn.microsoft.com/en-us/library/aa933131(SQL.80).aspx para usar índices agrupados.

Esto hará que las búsquedas int sean más lentas, ya que serán relegadas a utilizar un índice no agrupado.

1

¿Podría ser que haya un índice para su columna int pero no para su columna de fecha y hora? Mire el plan de ejecución.

+0

+1 buen punto - ¡compruebe el plan de ejecución! ¿El índice se está usando en absoluto? –

0

¿Ha agregado el campo DateTime al "índice" o a un índice exclusivo? ¿Está filtrando su selección por otro campo y el DateTime o solo este?

Debe tener un índice con todos los campos que está filtrando y preferiblemente en el mismo orden para optimizar el rendimiento.

+0

Lo había agregado a un índice existente, intenté crear un nuevo índice, se volvió relativamente rápido (0.5 segundos), pero aún más lento que una columna int. – silent

+0

Es importante hacer un buen índice mirando los campos en las afirmaciones "DÓNDE" y "ORDENAR POR" (y "AGRUPAR POR", si corresponde). Debería ser los mismos campos y en el mismo orden. Si no necesita todas las columnas de la tabla, haga SELECCIONAR solo con los campos deseados. Luego borre el caché y las estadísticas, y pruebe los resultados. También piense que es difícil seleccionar a la misma velocidad del índice agrupado en tablas con muchos datos. Esta es la razón para seleccionar cuidadosamente cuál debería ser el agrupado. –

6

en honor a la orden por parte del motor tiene dos alternativas:

  • escanear las filas utilizando un índice que ofrece el orden solicitado
  • ordenar las filas

primera opción es rápido, segundo es lento. El problema es que para ser utilizado, el índice tiene que ser un que cubra el índice. Lo que significa que contiene todas las columnas en la lista de proyección SELECT y todas las columnas utilizadas en las cláusulas WHERE (como mínimo). Si el índice no está cubriendo, el motor debería buscar el índice agrupado (es decir, la "tabla") para cada fila, a fin de recuperar los valores de las columnas necesarias. Esta búsqueda constante de valores es costosa, y hay un punto de inflexión en el que el motor (con razón) decidirá que es más eficiente escanear el índice agrupado y ordenar el resultado, ignorando de hecho su índice no agrupado. Para más detalles, vea The Tipping Point Query Answers.

en cuenta las tres preguntas siguientes:

SELECT dateColumn FROM table ORDER BY dateColumn 
SELECT * FROM table ORDER BY dateColumn 
SELECT someColumn FROM table ORDER BY dateColumn 

La primera de ellas se utilizará un índice no agrupado en dateColumn. Pero el segundo no usará un índice en dateColumn, probablemente elija un escaneo y clasifique en su lugar filas de 1M. Por otro lado, la tercera consulta se puede beneficiar de un índice en Table(dateColumn) INCLUDE (someColumn).

Este tema se cubre en su totalidad en MSDN, vea Index Design Basics, General Index Design Guidelines, Nonclustered Index Design Guidelines o How To: Optimize SQL Indexes.

En última instancia, la elección más importante de su diseño de tabla es el índice agrupado que utiliza. Casi siempre la clave principal (por lo general, una ID autoincrementada) se deja como índice agrupado, una decisión que beneficia solo ciertas cargas OLTP.

Y, por último, una pregunta bastante obvia: ¿Por qué en el mundo pediría 1 millón de filas? No puedes mostrarlos, ¿verdad? Explicar un poco más acerca de su caso de uso podría ayudarnos a encontrar una mejor respuesta para usted.

+0

Gracias Remus, no quiero mostrar más de 1 millón de registros, estoy usando el método row_number() para buscar, pero encontré cuando trato de buscar un número grande, como la página 50000 (20 rec/page), la consulta se vuelve muy lenta, pero si cambio el método de ordenamiento a ID, se vuelve casi 10 veces más rápido. – silent

+1

Pensé que esto debe ser row_number pagination. ¿Es LINQ, por casualidad? Su mejor opción es expresar la consulta de la siguiente manera: seleccione los ID de la página que le interesa (ed los 20 ID en la página 17) y luego recupere los detalles de esos 20 registros. Esto * puede * expresarse en T-SQL y también en LINQ y puede ser lo suficientemente rápido. Será mejor que publiques el esquema y las consultas involucradas. –

Cuestiones relacionadas