Hi.
Thanks for your input and expertise.
I am really puzzled by an apparent difference between table index key column order and its statistics order.
I was under understanding that index statistics mirror index definition. However, in my db 2470 index ordinal definitions match statistics definition but 66 do not.
I also can reproduce such discrepancy in 2008 R2, 2012 and 2014.
As per definition,
stats_column_id |
int |
1-based ordinal within set of stats columns |
This script duplicates this for me.
BEGIN TRAN GO use tempdb GO CREATE TABLE [dbo].[ItemProperties]( [itmID] [int] NOT NULL, [cpID] [smallint] NOT NULL, [ipuID] [tinyint] NOT NULL, CONSTRAINT [PK_ItemProperties_itmID_ipuID_cpID] PRIMARY KEY CLUSTERED ( [itmID] ASC, [ipuID] ASC, [cpID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO SELECT s.object_id ,s.name as stats_name ,( SELECT c.name + ', ' as [data()] FROM sys.stats_columns as sc JOIN sys.columns as c on c.object_id = sc.object_id and c.column_id = sc.column_id WHERE s.stats_id = sc.stats_id and s.object_id = sc.object_id ORDER BY sc.stats_column_id ASC FOR XML PATH('') ) as stats_column_list FROM sys.stats as s WHERE s.object_id = object_id('[dbo].[ItemProperties]') SELECT i.object_id ,i.name as index_name ,( SELECT c.name + ', ' as [data()] FROM sys.index_columns ic JOIN sys.columns c ON c.object_id = ic.object_id AND c.column_id = ic.column_id WHERE ic.object_id = i.object_id AND ic.index_id = i.index_id AND ic.is_included_column = 0 ORDER BY ic.key_ordinal ASC FOR XML PATH('') ) as index_column_list FROM sys.indexes i WHERE i.object_id = object_id('[dbo].[ItemProperties]') GO EXEC sp_helpstats '[dbo].[ItemProperties]', 'ALL' GO EXEC sp_helpindex '[dbo].[ItemProperties]' GO --DBCC SHOW_STATISTICS ("dbo.ItemProperties", PK_ItemProperties_itmID_ipuID_cpID) GO ROLLBACK
The result I get is this:
object_id stats_name
stats_column_list
1525580473 PK_ItemProperties_itmID_ipuID_cpID itmID, cpID, ipuID,
and
object_id index_name
index_column_list
1525580473 PK_ItemProperties_itmID_ipuID_cpID itmID, ipuID, cpID,
Also a query I used to discover this in my db is:
WITH stat AS ( SELECT s.object_id ,s.name as stats_name ,( SELECT c.name + ', ' as [data()] FROM sys.stats_columns as sc JOIN sys.columns as c on c.object_id = sc.object_id and c.column_id = sc.column_id WHERE s.stats_id = sc.stats_id and s.object_id = sc.object_id ORDER BY sc.stats_column_id FOR XML PATH('') ) as stats_column_list FROM sys.stats as s WHERE OBJECTPROPERTY(s.object_id, 'IsUserTable') = 1 ), ix AS ( SELECT i.object_id ,i.name as index_name ,( SELECT c.name + ', ' as [data()] FROM sys.index_columns ic JOIN sys.columns c ON c.object_id = ic.object_id AND c.column_id = ic.column_id WHERE ic.object_id = i.object_id AND ic.index_id = i.index_id AND ic.is_included_column = 0 ORDER BY ic.key_ordinal FOR XML PATH('') ) as index_column_list FROM sys.indexes i WHERE OBJECTPROPERTY(i.object_id, 'IsUserTable') = 1 ) SELECT OBJECT_SCHEMA_NAME(s.object_id) as TblSchema ,OBJECT_NAME(s.object_id) as TblName ,s.stats_name ,s.stats_column_list ,i.index_column_list FROM stat s JOIN ix i ON i.object_id = s.object_id AND i.index_name = s.stats_name WHERE i.index_column_list != s.stats_column_list ORDER BY s.stats_name
Thanks again for clarification.
Vladimir