Nuestro flujo ETL tiene una instrucción SELECT INTO de larga duración, que crea una tabla sobre la marcha y la completa con varios cientos de millones de registros.
La declaración se parece a algo como SELECT ... INTO DestTable FROM SrcTable
Para fines de monitoreo, nos gustaría tener una idea aproximada del progreso de esta declaración, mientras se ejecuta (recuento de filas, número de bytes escritos o similar).
Intentamos lo siguiente en vano:
-- Is blocked by the SELECT INTO statement:
select count(*) from DestTable with (nolock)
-- Returns 0, 0:
select rows, rowmodctr
from sysindexes with (nolock)
where id = object_id('DestTable')
-- Returns 0:
select rows
from sys.partitions
where object_id = object_id('DestTable')
Además, podemos ver la transacción en sys.dm_tran_active_transactions
, pero no pude encontrar una manera de obtener el recuento de filas afectadas en un determinado transaction_id
(algo similar a @@ROWCOUNT
quizás, pero con el transaction_id
argumento como).
Entiendo que en SQL Server, la instrucción SELECT INTO es tanto una instrucción DDL como una DML en una, y como tal, la creación implícita de la tabla será una operación de bloqueo. Todavía creo que debe haber alguna forma inteligente de obtener algún tipo de información de progreso mientras se ejecuta la declaración.
Respuestas:
Sospecho que
rows
ensys.partitions
0 es debido a que aún no se ha comprometido. Pero esto no significa que SQL Server desconozca qué irá allí si la transacción se confirma. La clave está en recordar que todas las operaciones pasan primero por el Buffer Pool (es decir, la memoria), independientemente de COMMIT o ROLLBACK de la operación. Por lo tanto, podemos buscarsys.dm_os_buffer_descriptors
esa información:Si desea ver los detalles, descomente la primera fila de elementos en la
SELECT
lista, comente las 3 líneas restantes.Probé ejecutando lo siguiente en una sesión y luego ejecutando repetidamente la consulta anterior en otra.
fuente
¿Uno fuera o en curso?
Si esta es una necesidad que se puede anticipar por adelantado *, puede usar
sys.dm_exec_query_profiles
Conexión 1 (sesión 55)
Conexión 2
Es posible que deba sumar los recuentos de filas devueltos si
SELECT INTO
está utilizando paralelismo .* La sesión que desea monitorear usando este DMV debe estar habilitada para la recopilación de estadísticas usando
SET STATISTICS PROFILE ON
oSET STATISTICS XML ON
. Solicitar un plan de ejecución "real" de SSMS también funciona (porque establece la última opción).fuente
No creo que haya una manera de obtener recuentos de filas, pero puede estimar la cantidad de datos escritos mirando:
Si tiene algún tipo de idea de cuántas páginas debería ocupar el montón cuando haya terminado, debería poder calcular el% completado. La última consulta no será rápida a medida que la tabla se agrande. Y probablemente sea más seguro ejecutar lo anterior debajo
READ UNCOMMITTED
(y no es frecuente que lo recomiendo, para nada).fuente
Si pudieras cambiar el
INSERT
de una un
entonces su
select count(*) from DestTable with (nolock)
consulta funcionaría.Si esto no es posible, puede usar sp_WhoIsActive (o profundizar en los DMV) para controlar cuántas escrituras hace la consulta. Esta sería una medida bastante aproximada, pero podría ser útil si basas el número de escrituras que normalmente hace.
Debería poder obtener un registro mínimo con lo
INSERT
anterior si agregaWITH (TABLOCK)
.fuente
INSERT
anterior si agregaWITH(TABLOCK)
BULK_OPERATION
bloquea.