2010-11-22 34 views
9

Tengo un escenario en el que hay una gran cantidad de datos de estado sobre un elemento. El estado del elemento se actualiza de minuto a minuto, y habrá cerca de 50,000 artículos en el futuro cercano. De modo que, en un mes, habrá alrededor de 2,232,000,000 filas de datos. Debo mantener al menos 3 meses en la tabla principal, antes de archivar datos anteriores.Particionado para el rendimiento de consultas en SQL Server 2008

Debo planificar consultas rápidas, basadas en un elemento específico (su ID) y un rango de datos (por lo general, hasta un rango de un mes) - p. seleccione A, B, C de la Tabla donde ID de elemento = 3000 y Fecha entre '2010-10-01' y '2010-10-31 23: 59: 59.999'

Entonces mi pregunta es cómo diseñar una estructura de partición para lograr eso?

Actualmente, estoy partición basada en "el identificador único del artículo" el (un int) mod "el número de particiones", de manera que todas las particiones se distribuyen por igual. Pero tiene el inconveniente de mantener una columna adicional en la tabla para actuar como la columna de partición a la función de partición, por lo tanto, mapear la fila a su partición. Todo eso agrega un poco de almacenamiento adicional. Además, cada partición se asigna a un grupo de archivos diferente.

+1

Eso es un poco de carga. Lea [aquí] (http://sqlblog.com/blogs/paul_nielsen/archive/2007/12/12/10-lessons-from-35k-tps.aspx) sobre escritura de alto volumen (tiene 50k filas * por segundo * entrante). Me intriga cómo va a resolver esto: no tengo experiencia con ese volumen/tasa de aumento) en absoluto – gbn

+0

¿Está tratando de diseñar para la eficacia de la consulta de escritura o la eficiencia de la consulta de lectura? ¿Qué tipo de cargas de lectura tienes? –

+0

¿Puede darnos más información sobre qué columnas hay en la tabla y qué tamaño de columna (ancho) devuelve en la consulta? –

Respuesta

10

El particionamiento nunca se hace para el rendimiento de la consulta. Con la partición el rendimiento será siempre peor, lo mejor que puede esperar es una gran regresión, pero nunca mejora.

Para el rendimiento de la consulta, cualquier cosa que una partición pueda hacer, y el índice puede hacerlo mejor, y esa debería ser su respuesta: indexar de manera apropiada.

El particionamiento es útil para casos de control de ruta IO (distribuir en volúmenes archivados/actuales) o para escenarios rápidos de conmutación de conmutación en cargas ETL. Así que entendería si tuviera una ventana deslizante y una partición por fecha para que pueda cambiar rápidamente los datos que ya no es necesario conservar.

Otro caso estrecho para el particionamiento es la contención del pestillo de inserción de la última página, como se describe en Resolving PAGELATCH Contention on Highly Concurrent INSERT Workloads. Su esquema de partición y caso de uso no parece ajustarse a ninguno de los escenarios en los que se beneficiaría (quizás es el último escenario, pero no está claro en la descripción), por lo que puede perjudicar el rendimiento.

+0

Comparé esta solución de tabla particionada con otra tabla que no se particionó y los resultados fueron ligeramente peores en la solución particionada (98ms vs 99ms) He usado 8 particiones, ahora intentaré usar 250 en su lugar, distribuido en 2 unidades y ver cómo se jugarán las cosas. – gsb

+0

Poco: dos (2) unidades, ¿va a haber solo dos unidades en el sistema de producción? –

0

Estoy de acuerdo con Remus, las particiones no van a mejorar las cosas, como muestran sus propios resultados.

Olvídese de las particiones, indexe la ID y la fecha, y ejecute en una caja con gran RAM; ¿cómo son los resultados?

1

Realmente no estoy de acuerdo con Remus Rusanu. Creo que la partición puede mejorar el rendimiento si hay una razón lógica (relacionada con sus casos de uso). Mi suposición es que podrías dividir SOLAMENTE en itemID. La alternativa sería usar también la fecha, pero si no puede predecir que un rango de fechas no cruzará los límites de una partición determinada (no hay dudas de que las consultas tendrán lugar en un solo mes), me quedaré con la partición itemId.

Si solo hay unos pocos elementos que necesita calcular, otra opción es tener un índice de cobertura: defina un ÍNDICE en su campo principal de diferenciación (ítem) que INCLUYE los campos que necesita para calcular.

CREATE INDEX idxTest ON itemId INCLUDE quantity; 
1

partición Aplicativo en realidad puede ser beneficioso para el rendimiento de las consultas. En tu caso tienes 50K ítems y 2G filas. Por ejemplo, podría crear 500 tablas, cada una denominada status_nnn donde nnn está entre 001 y 500 y "particionar" los estados de sus elementos por igual entre estas tablas, donde nnn es una función de la identificación del elemento. De esta forma, dada una identificación de artículo, puede limitar su búsqueda a priori al 0.2% de los datos completos (aproximadamente 4M filas).

Este enfoque tiene muchas desventajas, ya que probablemente tenga que lidiar con sql dinámico y otros problemas desagradables, especialmente si necesita agregar datos de diferentes tablas. PERO, definitivamente mejorará el rendimiento para ciertas consultas, por ejemplo. los que mencionas

El particionamiento esencialmente aplicativo es similar a la creación de un índice muy ancho y plano, optimizado para consultas muy específicas sin duplicar los datos.

Otro beneficio del particionado aplicativo es que en teoría (dependiendo de su caso de uso) podría distribuir sus datos entre diferentes bases de datos e incluso diferentes servidores. De nuevo, esto depende en gran medida de sus requisitos específicos, pero he visto y trabajado con enormes conjuntos de datos (miles de millones de filas) donde la partición aplicativa funcionó muy bien.

Cuestiones relacionadas