Portanto, eu tenho um processo simples de inserção em massa para pegar os dados da nossa tabela de preparação e movê-los para o nosso datamart.
O processo é uma tarefa simples de fluxo de dados com configurações padrão para "Linhas por lote" e as opções são "tablock" e "sem restrição de verificação".
A mesa é bastante grande. 587.162.986 com um tamanho de dados de 201 GB e 49 GB de espaço de índice. O índice clusterizado para a tabela é
CREATE CLUSTERED INDEX ImageData ON dbo.ImageData
(
DOC_ID ASC,
ACCT_NUM ASC,
MasterID ASC
)
E a chave primária é:
ALTER TABLE dbo.ImageData
ADD CONSTRAINT ImageData
PRIMARY KEY NONCLUSTERED
(
ImageID ASC,
DT_CRTE_DOC ASC
)
Agora, estamos tendo um problema em que BULK INSERT
via SSIS está executando incrivelmente lento. 1 hora para inserir um milhão de linhas. A consulta que preenche a tabela já está classificada e a consulta a preencher leva menos de um minuto para ser executada.
Quando o processo está em execução, posso ver a consulta aguardando a inserção BULK, que leva de 5 a 20 segundos e mostra um tipo de espera de PAGEIOLATCH_EX
. O processo é capaz apenas de INSERT
cerca de mil linhas por vez.
Ontem, enquanto testava esse processo no meu ambiente UAT, estava com o mesmo problema. Eu estava executando o processo algumas vezes e tentando determinar qual é a causa raiz dessa inserção lenta. De repente, começou a funcionar em menos de 5 minutos. Então eu executei mais algumas vezes, tudo com o mesmo resultado. Além disso, o número de inserções em massa que aguardavam 5 segundos ou mais caiu de centenas para cerca de 4.
Agora, isso é desconcertante, porque não é como se tivéssemos tido uma grande queda de atividade.
CPU durante a duração é baixa.
Nos momentos em que é mais lento, parece haver menos esperas no disco.
A latência do disco realmente aumenta durante o período em que o processo estava sendo executado em menos de 5 minutos.
E o IO foi muito mais baixo durante o período em que esse processo ocorre mal.
Eu já verifiquei e não houve crescimento de arquivos, pois os arquivos estão apenas 70% cheios. O arquivo de log ainda tem 50% para ir. O banco de dados está no modo de recuperação simples. O banco de dados possui apenas um grupo de arquivos, mas está espalhado por quatro arquivos.
Então, o que eu estou pensando A: por que eu estava vendo tempos de espera tão grandes nessas inserções em massa. B: que tipo de mágica aconteceu que a fez correr mais rápido?
Nota. Hoje corre como lixo novamente.
ATUALIZAÇÃO está atualmente particionada. No entanto, é feito em um método que é, na melhor das hipóteses, bobo.
CREATE PARTITION SCHEME [ps_Image] AS PARTITION [pf_Image]
TO ([FG_Image], [FG_Image], [FG_Image], [FG_Image])
CREATE PARTITION FUNCTION [pf_Image](datetime) AS
RANGE RIGHT FOR VALUES (
N'2011-12-01T00:00:00.000'
, N'2013-04-01T00:00:00.000'
, N'2013-07-01T00:00:00.000'
);
Isso deixa essencialmente todos os dados na 4ª partição. No entanto, já que tudo está indo para o mesmo grupo de arquivos. Atualmente, os dados são divididos de maneira bastante uniforme entre esses arquivos.
ATUALIZAÇÃO 2 Essas são as esperas gerais quando o processo está sendo executado de maneira inadequada.
Estas são as esperas durante o período em que eu fui capaz de executar o processo.
O subsistema de armazenamento é RAID conectado localmente, sem SAN envolvida. Os logs estão em uma unidade diferente. O controlador RAID é PERC H800 com tamanho de cache de 1 GB. (Para UAT) Prod é um PERC (810).
Estamos usando a recuperação simples, sem backups. É restaurado a partir de uma cópia de produção todas as noites.
Também configuramos o IsSorted property = TRUE
SSIS, já que os dados já estão classificados.
PAGEIOLATCH_EX
e ASYNC_IO_COMPLETION
estão indicando que está demorando um pouco para obter dados do disco na memória. Isso pode ser um indicador de um problema com o subsistema de disco ou pode ser uma contenção de memória. Quanta memória o SQL Server tem disponível?
ASYNC_NETWORK_IO
significa que o SQL Server estava aguardando o envio de linhas para um cliente em algum lugar. Suponho que esteja mostrando a atividade do SSIS consumindo linhas da tabela de preparação.