I am researching a DW reporting table that will grow very large. For simplicity, I will show the table as follows:
BigTable
--------
TableID INT IDENTITY NOT NULL,
CompanyName NVARCHAR(100) NOT NULL
Every query will use the company name to query within a partition of data (not a physical partition).
Since this table may contain over a billion rows and each company will have a pretty even distribution of data, querying by company should be as fast as possible. I am in the stages of setting up a few tests, but before doing so I thought I would ask and see if it would be a waste of time.
My idea was to determine that if each company's partition of data laid next to each other on disk via a clustered index, would data retrieval be any faster than just using a non-clustered index to cover CompanyName.
Example 1: Here is the variation where the IDENTITY column is the PK but not CLUSTERED. The CompanayName and TableID combine to make the Clustered Index so the data will be ordered by company on disk.
CREATE TABLE [dbo].[BigTable](
[TableID] [int] IDENTITY(1,1) NOT NULL,
[CompanyName] [nvarchar](100) NOT NULL,
CONSTRAINT [PK_BigTable] PRIMARY KEY NONCLUSTERED
(
[TableID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 97, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE UNIQUE CLUSTERED INDEX [CLUSTERED_ByCompanyName_TableID] ON [dbo].[BigTable]
(
[CompanyName] ASC,
[TableID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 97, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
GO
And here is the traditional way of creating tables with covering indexes.
CREATE TABLE [dbo].[BigTable](
[TableID] [int] IDENTITY(1,1) NOT NULL,
[CompanyName] [nvarchar](200) NOT NULL,
CONSTRAINT [PK_BigTable] PRIMARY KEY CLUSTERED
(
[TableID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 97, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [IX_ByCompanyName] ON [dbo].[BigTable]
(
[CompanyName] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 97, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
GO
Does anyone know right away if there would be any performance improvement to be had in using the first example over the second example?
EDIT: I am leaning towards using a clustered index with Company. The TableID is just autoincrement field to use as a PK if a row needs a unique reference. I feel that clustered Index Seeks/Scans are faster than Index Scan(s)/Seek(s).
I wish you could easily partition, or shard based on something like companyid.
A basic query would be in the form of
SELECT
SUM(FieldA) OVER (PARTITION BY ...) a,
COUNT(1) OVER (PARTITION BY...) b
...
FROM
BigTable
WHERE
CompanyName = 'NABISCO'
GROUP BY
....
ORDER BY
....
CompanyName
andTableId
then in your second example neither index is covering.