A menos que eu esteja entendendo mal a finalidade da coluna, o código a seguir indica que uma alteração na estrutura do índice clusterizado não altera a posição ordinal ( stats_column_id
) da coluna no sys.stats_columns DMV. (Testado em AdventureWorks2014, AdventureWorks2008R2)
select i.name, c.name, ic.column_id, ic.index_column_id
from sys.indexes i
join sys.index_columns ic
on i.object_id = ic.object_id
and i.index_id = ic.index_id
join sys.columns c
on i.object_id = c.object_id
and ic.column_id = c.column_id
where i.name = 'PK_BusinessEntityAddress_BusinessEntityID_AddressID_AddressTypeID'
order by ic.key_ordinal;
select sh.name,s.name, c.name, c.column_id, sc.column_id, sc.stats_column_id
from sys.stats s
join sys.stats_columns sc
on s.object_id = sc.object_id
and s.stats_id = sc.stats_id
join sys.columns c
on s.object_id = c.object_id
and sc.column_id = c.column_id
join sys.tables t
on s.object_id = t.object_id
join sys.schemas sh
on t.schema_id = sh.schema_id
where s.name = 'PK_BusinessEntityAddress_BusinessEntityID_AddressID_AddressTypeID'
order by sc.stats_column_id;
dbcc show_statistics('[Person].[BusinessEntityAddress]','PK_BusinessEntityAddress_BusinessEntityID_AddressID_AddressTypeID') with density_vector;
ALTER TABLE [Person].[BusinessEntityAddress] DROP CONSTRAINT [PK_BusinessEntityAddress_BusinessEntityID_AddressID_AddressTypeID]
GO
ALTER TABLE [Person].[BusinessEntityAddress] ADD CONSTRAINT [PK_BusinessEntityAddress_BusinessEntityID_AddressID_AddressTypeID] PRIMARY KEY CLUSTERED
(
AddressID ASC,
[BusinessEntityID] ASC,
[AddressTypeID] ASC
)
GO
select i.name, c.name, ic.column_id, ic.index_column_id
from sys.indexes i
join sys.index_columns ic
on i.object_id = ic.object_id
and i.index_id = ic.index_id
join sys.columns c
on i.object_id = c.object_id
and ic.column_id = c.column_id
where i.name = 'PK_BusinessEntityAddress_BusinessEntityID_AddressID_AddressTypeID'
order by ic.key_ordinal;
select sh.name,s.name, c.name, c.column_id, sc.column_id, sc.stats_column_id
from sys.stats s
join sys.stats_columns sc
on s.object_id = sc.object_id
and s.stats_id = sc.stats_id
join sys.columns c
on s.object_id = c.object_id
and sc.column_id = c.column_id
join sys.tables t
on s.object_id = t.object_id
join sys.schemas sh
on t.schema_id = sh.schema_id
where s.name = 'PK_BusinessEntityAddress_BusinessEntityID_AddressID_AddressTypeID'
order by sc.stats_column_id;
dbcc show_statistics('[Person].[BusinessEntityAddress]','PK_BusinessEntityAddress_BusinessEntityID_AddressID_AddressTypeID') with density_vector;
No entanto, os vetores de densidade indicam uma alteração na coluna inicial do objeto de índice/estatística. Isso é um mal-entendido fundamental da minha parte? Em caso afirmativo, como encontraria a coluna inicial de um objeto de estatísticas usando DMVs?
Versões testadas do SQL Server: 2008R2, 2014
Eu estava tendo o mesmo problema ao tentar reproduzir a maneira como os outros recuperam informações de índice das exibições sys.dm no SQL Server. Eu simplesmente não consegui descobrir a ordem das colunas no índice.
A seguir está um script que criei para determinar a ordem das colunas em qualquer índice para uma determinada tabela:
A coluna
key_ordinal
na tabela sys.index_columns é a ordem na qual as colunas são armazenadas no índice.Não há uma
key_ordinal
coluna para asys.stats_columns
tabela. A colunastats_column_id
apenas replica aindex_column_id
coluna do objeto que ela referencia.Há uma pequena diferença no texto do artigo sys.stats_columns (Transact-SQL) para a coluna
stats_column_id
:...e no artigo sys.index_columns (Transact-SQL) para a
key_ordinal
coluna:Eu acho que o
index_column_id
(sys.index_columns) estats_column_id
(sys.stats_columns) são equivalentes um ao outro e que apenas a tabela sys.index_columns tem uma coluna de ordenação, ou seja,key_ordinal
.Por todas as contas, este pode ser um comportamento com bug no sys.stats_columns DMV. Isso parece estar causando problemas quando uma estatística é atualizada por meio do índice pai. Acredito que isso se deva ao mecanismo com que as estatísticas estão sendo atualizadas em uma mudança de restrição.
Caso você crie uma estatística manualmente e depois deseje alterar as colunas, primeiro você deve descartar e recriar, o que força os metadados a serem atualizados no DMV em questão. Na operação que você demonstrou, parece haver uma situação em que os metadados não são atualizados em nenhuma circunstância (DBCC *, CHECKPOINT, reinicialização do servidor, atualização de estatísticas por meio da alteração do índice pai etc.) após a alteração. Do meu teste inicial, posso encontrar apenas um caso em que os metadados são atualizados corretamente, que é o cenário de soltar e recriar.
Você pode dar uma olhada no item Connect sobre o problema e votar conforme apropriado. Há uma consulta alternativa postada lá, mas seu mecanismo é baseado na correspondência do nome do índice com o nome da estatística e na utilização dos metadados do índice.