Estou tentando atualizar uma tabela de destino que tem uma linha de tamanho 5k para uma linha de tamanho 5k também.
Como é uma linha, é fácil saber o tamanho real da linha:
select *
from sys.dm_db_index_physical_stats(DB_ID('RODS_HSD_ES'),
OBJECT_ID(N'TBL_BM_HSD_SUBJECT_AN_148_REPRO'), NULL, NULL, 'DETAILED')
A tabela não foi alterada desde a criação. não vejo nenhuma razão para que falhe. Ideias?
sql-server
sql-server-2012
update
Yosi Dahari
fonte
fonte
Respostas:
O problema está relacionado ao fato de você estar atualizando a chave de cluster e a tabela de destino possui um esquema de particionamento 1 . Quando o SQL Server é solicitado a atualizar qualquer componente da chave de cluster, ele deve executar uma atualização híbrida
UPDATE
eDELETE
/ ou onde algumas das linhas são atualizadas no local e outras não.Se você remover o índice clusterizado da tabela de destino, verá a atualização funcionando.
A mensagem de erro, embora talvez um pouco enganadora, é precisa, pois o tamanho da linha resultante durante a atualização excede o tamanho máximo.
Sugiro que você considere alterar a estrutura da tabela para:
VARCHAR(MAX)
para todas essas colunas. Se você realmente não precisa de 2 GB de caracteres em uma única coluna, por que definir a coluna dessa maneira? Defina a coluna como o tamanho máximo que será encontrado realisticamente.V_MAX_xxx
,V_64_xxx
eV_512_xxx
colunas, etc.Para simplificar sua reprodução, convém eliminar o cursor e fazer apenas a seguinte operação DML:
A coluna acima é um dos componentes da chave de cluster e também a chave de particionamento (a atualização de outras colunas de chave de IC funciona bem).
Com o índice clusterizado no lugar, você recebe este erro:
Sem o índice clusterizado no lugar, a instrução é bem-sucedida.
1 Curiosamente, se eliminarmos o particionamento da reprodução, verificamos que a atualização foi bem-sucedida, mesmo com o índice clusterizado.
fonte
A atualização falha por razões muito semelhantes às que expliquei em resposta à sua pergunta anterior .
Nesse caso, como você está potencialmente atualizando várias linhas nas quais uma coluna de chave de um índice exclusivo é alterada * , o SQL Server cria um plano que inclui operadores Split, Sort e Collapse para evitar violações intermediárias de chave exclusiva (consulte este artigo para obter detalhes) .
O operador Sort, assim introduzido, encontra uma linha intermediária (incluindo as despesas gerais) de uma largura que excede o limite; portanto, é gerado um erro. Adicionar uma
OPTION (ROBUST PLAN)
dica à consulta de atualização mostra que isso é inevitável:Os relacionamentos de dados de origem / destino não são claros para mim em uma breve olhada, mas se você puder garantir que cada operação de atualização afetará no máximo uma linha, poderá evitar a necessidade de Dividir / Classificar / Recolher adicionando
TOP (1)
à instrução de atualização:Isso é um pouco complicado, no entanto. Idealmente, a construção da instrução de atualização e os índices devem fornecer informações suficientes para o otimizador, para que ele possa ver que no máximo uma linha será atualizada. Em particular, é uma prática recomendada escrever instruções de atualização determinísticas .
Dado o design estranho e a falta de clareza na pergunta, não vou nem tentar decifrar os relacionamentos de dados, nem as alterações de consulta e índice que seriam necessárias para conseguir isso em detalhes.
* Como Martin Smith apontou em um comentário, isso não seria um problema nessa situação específica se a tabela não fosse particionada. Onde a atualização define a chave com o mesmo valor determinístico em todas as linhas, Dividir / Classificar / Recolher não é necessário, a menos que a tabela também seja particionada nessa chave. Portanto, uma solução alternativa para essa consulta é não particionar a tabela no sampletime .
fonte