2011-01-08 9 views
5

Tengo una tabla en SQL Server 2008 (SP2) que contiene 30 millones de filas, 150GB de tabla, hay un par de columnas int y dos columnas nvarchar (max): una que contiene texto (desde 1 -30000 caracteres) y uno que contiene xml (hasta 100000 caracteres).La actualización de la tabla lleva mucho tiempo

La tabla no tiene claves o índices principales (es una tabla de etapas). Así que estoy ejecutando una consulta:

UPDATE [dbo].[stage_table] 
SET [column2] = SUBSTRING([column1], 1, CHARINDEX('.', [column1])-1); 

la consulta se ejecuta durante 3 horas (y que todavía no se ha completado), que creo que es demasiado largo. ¿Lo es? Veo que hay una tasa de lectura constante de 5 MB/s y una velocidad de escritura de 10 MB/s en un archivo .mdf.

¿Cómo puedo saber por qué la consulta se está ejecutando durante tanto tiempo? El "servidor" es i7, 24 GB de RAM, discos SATA en RAID 10.

Actualizado:

tabla contiene una columna int, dos (20) columnas nvarchar y dos columnas nvarchar (max). Column1 y Columns2 en la cláusula de actualización anterior son columnas nvarchar (20). Las columnas "grandes" no se actualizan.

¡Muchas gracias!

+0

¿Están las columnas de actualizaciones indexadas? – IamIC

Respuesta

3

Honestamente, eso es una gran cantidad de trabajo que estás haciendo (búsqueda de texto y reemplazo en 150 gigabytes). Si los datos ordenados se originaron fuera de la base de datos, podría considerar realizar operaciones de texto allí, sin ninguna sobrecarga de la base de datos.

+0

Gracias por su respuesta. He actualizado la pregunta. La columna1 y la columna2 son columnas nvarchar (20), por lo que el texto que se busca no es tan grande, solo la tabla es enorme. – rrejc

+0

Sospecho que todavía es cierto que sería mejor que hicieras esto fuera de la base de datos. Hay una gran cantidad de gastos generales en el procesamiento y la actualización de cada una de esas filas, no tanto como si estuvieras operando en toda la base de texto, pero aún así mucho. –

1

Está realizando una manipulación de cadena en un campo, algo en lo que SQL es notoriamente malo. Considere escribir una función SQL CLR que haga lo que necesita y use eso en lugar de SUBSTRING([column1], 1, CHARINDEX('.', [column1])-1).

+0

Si no hay criterios de selección, ¿por qué es importante la falta de índices? – sgmoore

+1

No veo cómo un índice puede mejorar la consulta. Solo tiene que ser un escaneo completo de la tabla. –

+2

¿Por qué un índice aceleraría esta ACTUALIZACIÓN? No hay una cláusula WHERE. De hecho, para esta ACTUALIZACIÓN un índice ralentizaría las cosas (debido al tiempo necesario para actualizar los índices). –

0

Una forma práctica de comprobar si algo fuera de lo común es actualizar solo algunos de los datos. Escriba una vista que seleccione las 10 000 primeras filas y ejecute la actualización en la vista.

Si 10.000 filas se actualizan en lo que cabría esperar que fuera "normal" para su servidor, se seguiría que son solo "una gran cantidad de datos para actualizar".

Si esta pequeña actualización parece indebidamente larga, investigue más.

Al menos esto le proporciona un campo de pruebas decente.

1

Una forma práctica de comprobar si algo fuera de lo común es actualizar solo algunos de los datos. Escriba una vista que seleccione las 10 000 primeras filas y ejecute la actualización en la vista.

Si hay 10.000 actualizaciones en lo que esperaría que fueran "normales" para su servidor, se seguiría que son solo "una gran cantidad de datos para actualizar".

Si estas pequeñas actualizaciones parecen excesivamente largas, investigue más.

Al menos esto le proporciona un campo de pruebas decente.

1

Aquí hay algunas opciones. Pero sin más información sobre lo que pretende hacer con los datos después de que se realiza esta actualización, la respuesta de Larry Lustig parece ser la más adecuada. Pero existen otras opciones:

  • Cree la columna2 como una columna calculada en lugar de una columna física.
  • Realizar el cálculo mientras tira de los datos de la tabla de ensayo (que es también lo que tendría lugar si vas con el punto anterior.
  • columna2 Índice y luego realizar las actualizaciones en trozos de 10.000 registros más o menos donde columna2 es nula. esto evitará que el tamaño de la transacción implícita abajo, que es probablemente lo que está matando actualmente el rendimiento de su.
1

no he hecho este tipo de procesamiento en SQL Server, así que no estoy seguro de si el consejo se aplica completamente. Pero estoy lo suficientemente seguro como para sugerir que lo pruebes.

Lo que suelo hacer en Oracle es evitar las actualizaciones por completo al procesar TODAS las filas en una situación como la que describe (usuario único, evento por lotes).

O migro la lógica de la instrucción de actualización a la instrucción que insertó las filas. O si esto no es posible, creo una nueva tabla y coloco la lógica de actualización en la lista de selección. Por ejemplo, en lugar de hacer

UPDATE [dbo].[stage_table] 
SET [column2] = SUBSTRING([column1], 1, CHARINDEX('.', [column1])-1); 

que haría:

create table stage_table2 as 
    select column1 
     ,substring(column1, 1, charindex('.', column1)-1) as column2 
     ,column3 
     ,column4 
    from stage_table; 

drop table stage_table; 

alter table stage_table2 rename to stage_table; 
-- re-create indexes and constraints, optionally gather statistics 

yo también podría hacerlo con consultas en paralelo y la opción NOLOGGING para generar muy poco hacer de nuevo y no se puede deshacer del todo, lo que superar una la declaración de actualización con un margen tan grande ni siquiera es gracioso :) Por supuesto, esto se debe a las funciones internas de Oracle, pero creo que también sería posible replicarlo con SQL Server. Sin embargo, hay algo en su descripción que puede hacer que este sea un enfoque menos eficiente. Tenía algunas columnas de texto muy grandes que tendría que "arrastrar" en la instrucción CTAS.

Además, debe investigar la configuración de su hardware porque no es apto para trabajar con la cantidad de datos que le ha enviado. O hay algo incorrecto en la configuración, o si tiene un montón de otras actividades pasando:

puedo ver que hay una constante leer tasa de 5 MB/s y la velocidad de 10MB/s a escribir. archivo mdf

Puedo vencer eso en mi computadora portátil de novias de 2 años. Dada una velocidad de lectura de 5 mb/sy una tabla de 150 GB, tomaría 8.5 horas escanear la tabla solo una vez. Esto supone que la base de datos agrega un 0% de sobrecarga, que es , no el caso.

Cuestiones relacionadas