7

Mis dos preguntas son:Índices agrupados en columnas que no son de identidad para acelerar inserciones masivas?

  • ¿Puedo usar los índices agrupados para acelerar hasta inserciones masivas en grandes mesas?
  • ¿Puedo seguir utilizando eficientemente las relaciones de clave foránea si mi columna IDENTIDAD ya no es el índice agrupado ?

Para elaborar, tengo una base de datos con un par de tablas muy grandes (entre 100-1000 mln filas) que contienen datos de la empresa. Por lo general, hay datos de entre 20 y 40 empresas en dicha tabla, cada una como su propio "fragmento" marcado por "identificador de empresa" (INT). Además, cada empresa tiene alrededor de 20 departamentos, cada uno con su propio "subchunk" marcado por "DepartmentIdentifier" (INT).

Ocurre con frecuencia que se agregue o elimine toda una "porción" o "subchunk" de la tabla. Lo primero que pensé fue utilizar Table Partitioning en esos fragmentos, pero como estoy usando SQL Server 2008 Standard Edition, no tengo derecho. Aún así, la mayoría de las consultas que tengo se ejecutan en un "fragmento" o "subchunk" en lugar de en la tabla como un todo.

He estado trabajando para optimizar estas tablas para las siguientes funciones:

  1. consultas que se ejecutan en subfragmentos
  2. consultas "marco de referencia" que se ejecutan en la tabla en su conjunto
  3. Inserción/eliminando grandes trozos de datos.

Para 1) y 2) No he encontrado muchos problemas. He creado varios índices en campos clave (que también contienen CompanyIdentifier y DepartmentIdentifier, donde es útil) y las consultas se ejecutan correctamente.

Pero para 3) he tenido problemas para encontrar una buena solución. Mi primera estrategia fue desactivar siempre los índices, insertar a granel un gran bloque y reconstruir índices. Esto fue muy rápido al principio, pero ahora que hay muchas compañías en la base de datos, se necesita mucho tiempo para reconstruir el índice cada vez.

Por el momento, mi estrategia ha cambiado a simplemente dejar el índice encendido durante la inserción, ya que ahora parece ser más rápido. Pero quiero optimizar aún más la velocidad de inserción.

Parece que he notado que al agregar un índice agrupado definido en CompanyIdentifier + DepartmentIdentifier, la carga de nuevos "fragmentos" en la tabla es más rápida. Antes de abandonar esta estrategia a favor de agregar un índice agrupado en una columna de IDENTIDAD, varios artículos me indicaron que el índice agrupado está contenido en todos los demás índices, por lo que el índice agrupado debería ser lo más pequeño posible. Pero ahora estoy pensando en revivir esta vieja estrategia para acelerar los insertos. Mi pregunta, ¿sería prudente o sufriré éxitos de rendimiento en otras áreas? ¿Y esto realmente acelerará mis insertos o es solo mi imaginación?

Tampoco estoy seguro de si en mi caso es realmente necesaria una columna de IDENTIDAD. Me gustaría poder establecer relaciones de claves externas con otras tablas, pero ¿también puedo usar algo como un esquema CompanyIdentifier + DepartmentIdentifier + [uniquifier] para eso? ¿O tiene que ser un número de IDENTIDAD fragmentado en toda la mesa?

Muchas gracias por cualquier sugerencia o explicación.

+0

¿Ha buscado Vistas particionadas para resolver su problema de "trozos" o no son adecuadas? –

+0

No creo que pueda usarlos en SQL Server Standard Edition. – thomaspaulb

+0

Sí, estos están disponibles en edición estándar. –

Respuesta

3

Bueno, lo puse a prueba, y al poner un índice agrupado en las dos columnas "que definen el fragmento" aumenta el rendimiento de mi tabla.

Insertar un fragmento es ahora relativamente rápido en comparación con la situación en la que tenía una clave de IDENTIDAD agrupada, y tan rápido como cuando no tenía ningún índice agrupado. Eliminar un fragmento es más rápido que con o sin índice agrupado.

Creo que el hecho de que todos los registros que deseo eliminar o insertar estén garantizados para estar todos juntos en una cierta parte del disco duro hace que las tablas sean más rápidas, me parece lógico.


actualización: Después de un año de experiencia con este diseño Puedo decir que para que este método funcione, es necesario programar la reconstrucción regular de todos los índices (lo hacemos una vez por semana). De lo contrario, los índices se fragmentarán muy pronto y se perderá el rendimiento. Sin embargo, estamos en un proceso de migración a un nuevo diseño de base de datos con tablas particionadas, que es básicamente mejor en todos los sentidos, excepto por el costo de licencia de Enterprise Server, pero ya lo hemos olvidado. Al menos yo tengo.

+2

Eso es exactamente correcto. Mire ** solo el modelo de datos ** en los enlaces al final de [esta respuesta] (http://stackoverflow.com/questions/4310769/bulletin-board-database-optimisation/4311900#4311900). Los IC se diseñaron para bases de datos Relacionales; nota las llaves. Particularmente bueno para cualquier consulta de rango; distribución de datos (lo que usted llama "fragmentación", insertar expansión de carga, recorte automático en la página y nivel de extensión. Lo único que no debe hacer es agrupar en una tecla monótona (lo contrario de su diseño). Hay un poco más entre el CI y el "disco duro", pero usted llegará a eso a tiempo. – PerformanceDBA

+0

Gracias. Aun así, el CI en mis "fragmentos" no me está dando el rendimiento que quiero y después de algunas pruebas preliminares con SQL Server Enterprise Table Partitioning I Me inclino por eso, especialmente porque me permitirá eliminar e insertar "trozos" sin bloquear toda la tabla durante mucho tiempo. ¿Seguiría ese razonamiento o sugeriría algo diferente? – thomaspaulb

1

Un índice agrupado es un índice físico, una estructura de datos físicos, un orden de fila. Si inserta en el medio del índice agrupado, los datos se insertarán físicamente en el medio de los datos actuales. Me imagino un grave problema de rendimiento en este caso. Solo sé esto por la teoría, porque si hago esto en la práctica, será un error según mi conocimiento teórico.

Por lo tanto, solo uso (y aconsejo el uso) de índices agrupados en campos que siempre, físicamente, se insertan al final, preservando el orden.

Un índice agrupado se puede colocar en un campo de fecha y hora que marca el momento de la inserción o algo así, porque físicamente se ordenarán después de agregar una fila. La identidad también es un buen índice agrupado, pero no siempre es relevante para las consultas.

En su solución coloca un campo [uniquifier], pero ¿por qué hacer esto cuando puede poner una identidad que hará exactamente eso? Será único, físicamente ordenado, pequeño (para claves externas en otras tablas significa índice más pequeño), y en algunos casos más rápido.

¿No puedes probar esto, experimentar? Tengo una situación similar aquí, donde tengo 4 mil millones de filas, constantemente estoy insertando (hasta 100 por segundo), la tabla no tiene clave principal ni índice agrupado, por lo que las proposiciones en este tema también son muy interesantes para mí.

+1

Los índices agrupados solo están en orden físico si no hay fragmentación. Es posible que el orden lógico y físico sea diferente. –

+0

Gracias por esa corrección. ¿Estoy aplicando la falta de fragmentación mediante el uso de estos métodos? ¿Qué tan malo es la fragmentación de todos modos? – AlexanderMP

+2

Es una corrección sin sentido. Los índices agrupados están en orden físico por definición. Que la tabla puede estar fragmentada es ** otro nivel ** de investigación, no cambia la definición. Diciendo eso, es tan tonto como decir que si estás usando RAID5, entonces todo está fragmentado, lo que implica: así que no te molestes con ** ningún ** índice. Si sigues la PageChain, está en orden. Si lees en serie (lo que no es posible), aparecerá fragmentado. Si no tiene CI, tiene un Heap. Lea sobre esto. Nunca se agrupe en IDENTIDAD, usted garantiza un punto de acceso en la última página (insertar). – PerformanceDBA

1

¿Puedo usar índices agrupados para acelerar inserciones masivas en tablas grandes?

¡Nunca! Imagina otro millón de filas que necesitas poner en esa tabla y haz que se ordenen físicamente, es una pérdida colosal en el rendimiento a largo plazo.

¿Puedo seguir usando de manera eficiente las relaciones de claves foráneas si mi columna de IDENTIDAD ya no es el índice agrupado?

Absolutamente. Por cierto, el índice agrupado no es una bala de plata y puede ser más lento que su índice ordinario.

+0

¿No está de acuerdo con [esta declaración] (http://www.simple-talk.com/sql/database-administration/brads-sure-guide-to-indexes/)? "Es más rápido insertar filas en una tabla con un índice agrupado como la clave principal que insertar los mismos datos en un montón que tiene un índice no agrupado como clave principal. Esto es así independientemente de si la clave principal es monótonamente creciente o no ". –

+0

¿Por qué * no quiero * Quiero que se ordenen físicamente en la empresa/departamento? Solo estoy agregando fragmentos basados ​​en esa combinación, no agregaré conjuntos mixtos (nunca). Entonces, para agregarlos, solo tendría que tocar una parte física del disco duro. Además, tengo muchas consultas que se ejecutan solo en un subconjunto único basado en esas columnas. – thomaspaulb

+0

@Martin Smith, @littlegreen Estoy hablando de almacenamiento de datos donde tienes que lidiar con millones de registros que deben insertarse entre los datos existentes si hay un índice agrupado en esa tabla. Y cuando elimina ese índice agrupado, estos datos se anexan al final de la tabla, lo que obviamente es más rápido. –

0

He estado jugando con algunas cosas etl el último poco. Pasé por jsut insertando regularmente en la tabla, luego quitando y leyendo índices antes y después de la inserción, intenté fusionar declaraciones, luego finalmente intenté ssis. Estoy vendido en ssis. Ayer mismo logré cortar un proceso de etl (~ 24 millones de registros, ~ 6 gb) de ~ 1-1 1/2 horas por ejecución a ~ 24 minutos, jsut al permitir que ssis maneje los insertos.

Creo que con los servicios avanzados usted debería poder usar ssis.

+0

Hasta donde yo sé, SSIS no es más rápido que hacer una operación BULK INSERT. – thomaspaulb

+0

genial. No me he equivocado con la inserción masiva. – DForck42

1

Eche un vistazo a la API System.Data.SqlClient.SqlBulkCopy. Dado sus requisitos para escribir números significativos de filas dentro y fuera de la base de datos, ¿podría ser lo que necesita?

La copia masiva transmite los datos a la tabla en una sola operación y luego realiza la comprobación del índice una vez. Lo uso para copiar 500,000 filas dentro y fuera de una tabla de base de datos y su rendimiento es un orden de magnitud mejor que cualquier otra técnica que he probado, suponiendo que su aplicación pueda ser estructurada para usar la API.

+0

Por lo que sé, ambos SSIS y la operación BULK INSERT hacen uso de la misma técnica que esta API. Ahora estoy usando SSIS al leer archivos, y cuando copio entre tablas solo uso SQL normal. ¿Puede esta API copiar entre tablas? – thomaspaulb

0

(dado que ya ha elegido la respuesta y dado a sí mismos los puntos, esto es proporcionado como un servicio gratuito, un acto de caridad!)

Un poco de conocimiento es algo peligroso. Hay muchos problemas a considerar; y deben ser considerados juntos. Tomar cualquier tema y examinarlo de manera aislada es una manera muy fragmentada de administrar una base de datos: siempre encontrará una verdad nueva y cambiará todo lo que pensó antes. Antes de iniciarlo, lea esto ▶question/answer◀ para contexto.

No se olvide, estos días cualquiera con un teclado y un módem puede publicar sus "documentos". Algunos de ellos trabajan para MS, evangelizando la última "mejora"; otros publican informes brillantes de características que nunca han usado, o usado una sola vez, en un contexto, pero publican que funciona en todos los contextos. (Mire la respuesta de Spence: es entusiasta y "vendido" pero bajo escrutinio, las declaraciones son falsas, no es una mala persona, solo típico de las masas en el mundo de EM y cómo operan; cómo lo publican)

  • Nota: Utilizo el término MicroSofties para describir a las personas que creen en la noción de que cualquier persona no calificada puede administrar una base de datos; y ese MS arreglará todo. No pretende ser un insulto, más como un cariño, debido a la creencia en la magia y la suspensión de las leyes de la física.

agrupados índices

fue diseñada para bases de datos relacionales, por los ingenieros reales (Sybase, MS adquirió antes del código) que tienen más cerebro que todos EM juntos. Las bases de datos relacionales tienen claves relacionales, no las Id claves iOt. Estas son teclas de varias columnas, que distribuyen automáticamente los datos y, por lo tanto, la carga de inserción, por ej. insertando Facturas para varias Compañías todo el tiempo (aunque no en nuestro caso discutido de "trozos").

  • si tiene buenas claves relacionales, IC proporcionar un rango de consultas (su (1) & (2)), y otras ventajas, que NCIS simplemente no tienen.

  • Comenzando con las columnas Id, antes de modelar y normalizar los datos, dificulta severamente los procesos de modelado y normalización.

  • Si tiene una base de datos Id, entonces tendrá más índices que los que no. Los contenidos de muchas bases de datos de MS no son "relacionales", comúnmente son sistemas de archivo no normalizados, con muchos más índices de los que tendría una base de datos normalizada. Por lo tanto, hay un gran impulso, muchas "mejoras" de la EM para intentar acelerar estos abortos. Repare el síntoma, pero no se acerque al problema que causó el síntoma.

  • En SQL 2005 y nuevamente en 2008, MS ha tenido problemas con los CI, y el resultado es que ahora son mejores en algunos aspectos, pero empeora en otros aspectos; la universalidad de los CI se ha perdido.

  • No es correcto que NCIS llevar el CI (CI es la estructura básica de almacenamiento único, el NCIS son secundarios, y depende de la IC, por eso cuando se vuelva a crear un CI, todo el NCIS son automáticamente recreado). Los NCI llevan la clave CI en el nivel de la hoja.

  • Microsoft tiene sus problemas, que cambian con las versiones principales (pero no se eliminan):

    • y en la EM no se hace esto de manera eficiente, por lo que el índice de NCI tamaño es grande; en el DBMS empresarial cuando se hace de manera eficiente, esto no es una consideración.

    • En el mundo MS, por lo tanto, es solo la mitad de verdad, que la clave CI debe ser lo más corta posible. Si entiende que la consideración es del tamaño de los NCI, y si está dispuesto a incurrir en ese gasto, regresa por una tabla que es muy rápida debido a un CI cuidadosamente construido, entonces esa es la mejor opción.

    • El consejo común de que el CI debe ser la columna cero de Id es totalmente erróneo. El peor candidato para una clave CI es un valor monótonamente creciente (IDENTIDAD, FECHA HORA, etc.). Por qué ? porque ha garantizado que todas las inserciones simultáneas luchan por la ubicación de inserción actual, la última página del índice.

    • El verdadero propósito de Partitioning (que MS proporcionó 10 años después de los proveedores de Enterprise) es distribuir esta carga. Claro, entonces tienen que proporcionar un método para asignar las particiones, adivinen qué, nada más que una clave relacional; pero para empezar, ahora la Id iot clave está distribuida en 32 o 64 particiones, proporcionando una mejor concurrencia.

  • el CI debe ser único. Los db relacionales exigen claves únicas, por lo que no es necesario.

    • Pero para los aficionados que han vertido su contenido no relacionales en la base de datos, si no saben esta regla, pero saben que la IC difunde los datos (un poco de conocimiento es algo peligroso), que mantenga su Id iot clave en un NCI (bueno) pero crean el CI en una clave única casi-pero-no-bastante. Mortal. Los IC deben ser únicos, eso es una demanda de diseño. Duplicado (recuerde que estamos hablando de clave CI aquí) las filas están fuera de la página, ubicadas en páginas de desbordamiento y la (última) página; y constituyen un método para fragmentar mal la Cadena de páginas.

    • Actualización, ya que este punto está siendo cuestionado en otro lugar. Ya he indicado que la MS sigue cambiando los métodos sin solucionar el problema.

      • El MS Online manual, con sus cuadros bonitos (no diagramas técnicos) nos dice que en 2008, que han sustituido (sustituida una por otra) Páginas de desbordamiento, con la adorable "Uniqueifier".

      • Eso satisface totalmente las MicroSofties. Los IC no únicos no son un problema. Se maneja por magia. Caso cerrado.

      • Pero no hay lógica o integridad en las declaraciones, y personas calificadas harán las preguntas obvias: ¿dónde se encuentra este "Uniqueifier"? En cada fila, o solo las filas que necesitan "Uniqueizing". DBBC PAGE muestra que está en cada fila. Así que MS acaba de agregar una columna secreta de 4 bytes (que incluye el manejo de la sobrecarga) a cada fila, en lugar de unas pocas páginas de desbordamiento para las filas que no son únicas. Esa es la idea de ingeniería de MS.

      • End Actualizar

    • De todos modos, el punto sigue siendo, que el CIS no únicos tienen una sobrecarga considerable (ahora más que antes) y debe ser evitado. es mejor que agregue una columna de 1 o 2 bytes usted mismo para forzar la unicidad. .

  • Por lo tanto, sin cambios desde el principio (1984), el mejor candidato para un implante coclear es una clave relacional única de varias columnas (no puedo decir que la suya es con seguridad, pero sin duda se ve como él).

  • Y coloque las teclas que aumentan monótonamente (IDENTIDAD, FECHA) en un NCI.

  • Recuerde también que el CI es una estructura de almacenamiento única, que elimina el (de otro modo) Heap; el CI B-Tree está casado con las filas en el nivel Leaf; la entrada de nivel de hoja es la fila. Eso garantiza una lectura menos en cada acceso.

    • Por lo tanto, no es posible que un NCI + Heap pueda ser más rápido que un CI. Anther mito común en el mundo de MS que desafía las leyes de la física: navegar un B-Tree y escribir en el lugar donde ya estás, tiene que ser más rápido que adicionalmente escribiendo la fila en una estructura de almacenamiento separada. Pero las MicroSofties sí creen en la magia, han suspendido las leyes de la física.
      .
  • Hay muchas otras características que necesita para aprender y usar, voy a mencionar al menos FILLFACTOR y RESERVEPAGEGAP, para dar este post un poco de integridad. No use estas características hasta que las comprenda. Todas las características de rendimiento tienen un costo que debe comprender y aceptar.

  • Los CI también se recortan automáticamente en el nivel de página y extensión, no hay espacio desperdiciado. Las divisiones de página son algo por lo que hay que controlar (inserciones aleatorias solamente), y eso se puede modular fácilmente mediante FILLFACTOR y RESERVEPAGEGAP.

  • Y lea el sitio de SO para Clustered Indices, pero tenga en cuenta todo lo anterior, esp. los primeros dos paras.

su caso específico

  • Por todos los medios, a deshacerse de sus claves suplentes (Id columnas IOT), y reemplazarlos con verdaderas claves relacionales naturales. Los sustitutos son siempre una clave e índice adicional; ese es un precio que no debe olvidarse o tomarse a la ligera.

  • CompanyIdentifier + DepartmentIdentifier + [uniquiefier] es exactamente de lo que estoy hablando. Ahora observe que ya son INT, y muy rápido, por lo que es muy tonto para agregar a NUMERIC (10,0) Id iot Key. Use una columna de 1 o 2 bytes para forzar la unicidad.

  • Si obtiene este derecho, es posible que no necesite una licencia de Partición.

  • CompanyIdentifier + DepartmentIdentifier + [uniquifier] es el candidato perfecto (sin saber nada sobre su db distinto del que ha publicado) para un CI, en el contexto que realiza la eliminación masiva/insertar periódicamente. Detallado arriba.

    • Al contrario de lo que otros han declarado, esto es algo bueno, y no fragmenta el IC. Digamos que tiene 20 compañías y elimina 1, que constituye el 5% de los datos. La totalidad de PageChain, que era razonablemente contigua, ahora está relegada a FreePageChain, contigua e intacta. Para ser precisos, tiene un único punto de fragmentación, pero no de fragmentación en el sentido del uso normal de la palabra. Y adivina qué, si te das la vuelta y haces una inserción masiva, ¿dónde crees que irán los datos? Así es exactamente la misma ubicación física que las filas eliminadas. Y FreePageChain se mueve a PageChain, extent y page a la vez.
      .
  • pero lo que es alarmante es que usted no sabía acerca de la demanda de CI para ser único. Es triste que los MicroSofties escriban basura, pero no por qué/en qué se basa cada regla simplista; no la información central El síntoma exacto de los elementos de configuración no únicos es que la tabla será muy rápida inmediatamente después de DROP/CREATE CI, y luego disminuirá con el tiempo. Un buen IC Único mantendrá su velocidad, y tomaría un año disminuir la velocidad (2 años en mi gran banco de datos bancarios activos).

  • 4 horas es un tiempo muy largo para 1 mil millones de filas (puedo recrear un CI en 16 mil millones de filas con una clave de 6 columnas en 3 minutos en una plataforma empresarial). Pero, en cualquier caso, eso significa que debe programarlo como un mantenimiento semanal regular o de demanda.

  • ¿por qué no utiliza la opción WITH SORTED_DATA? ¿No fueron sus datos ordenados antes de la caída? Esta opción reescribe las páginas de CI no hojas pero no las hojas (que contienen las filas). Solo puede hacerlo si está seguro de que los datos fueron ordenados. No usar esta opción reescribe todas las páginas, en orden físico.

Ahora, por favor sea amable. Antes de hacerme veinte preguntas, lea un poco y comprenda todos los problemas que he definido aquí.

+11

+1 para el ergy usted ingresa, +1 para sugerir CI únicos, +1 para WITH_SORTED_DATA, -1 para demasiada información offtopic, -1 para falta de respeto a Spence, -1 para 'MicroSofties', y -1 para uso molesto de 'Idiot' para Columnas Id. Realmente me enojas porque estás dando información útil, pero viene con un gran paquete de insultos. No puedo, con buena conciencia, votar, aceptar o incluso utilizar esta respuesta, porque si lo hago, alentaré tu comportamiento. Lo he marcado como ofensivo, así que dejen que las operaciones se encarguen de eso. – thomaspaulb

+1

como nota al margen, aumentando monotónicamente los valores: muchos sistemas son * query * intensivos, no * insert * intensive. En tales casos, tener el IC reflejando el más común "Necesito este rango" (que generalmente es un rango de identificación de fila o un intervalo de tiempo) * con un rendimiento óptimo * es ideal. –

+2

@Marc. Yo trabajo con ambos. Eso es incorrecto. Los sistemas de consulta intensiva necesitan consultas de rango, sí, pero en claves relacionales reales, no en Ids. Las series temporales siempre deben manejarse como un hijo del padre (que tiene claves reales). Id forzar uniones innecesarias, que pueden eliminarse. si está manejando series de tiempo e Id. como la columna principal o única de la tabla, tiene un montón de datos, no una base de datos; tan seguro que es muy lento y necesitas todas las mejoras que puedas obtener. Pero si retrocede y maneja el problema causante (claves 'Id'iot en lugar de Llaves relacionales), obtendrá un rendimiento mucho mayor. – PerformanceDBA

Cuestiones relacionadas