I have this table with millions of rows: Recording (Id, CampaignId, CallDateTime, Phone, etc)
And I have 2 different reports on that table:
--By Date:
declare @CampaignId int = 1, @Date date = '2023-06-27'
select * from Recording
where CampaignId = @CampaignId and cast(CallDateTime as date) = @Date
--By Phone:
declare @CampaignId int = 1, @Phone varchar(9) = '987654321'
select * from Recording
where CampaignId = @CampaignId and Phone = @Phone
It should have index, but how? With multiple columns (CampaignId, CallDateTime, Phone)? Or one index for every report (CampaignId, CallDateTime) and (CampaignId, Phone)?
Thanks.
2条答案
按热度按时间wvt8vs2t1#
First, you should fix the first query, or no index will be useful. It should be:
The general rule is never wrap the column in an expresson; always write the query so the parameter is instead. And check the Data Type Precedence to ensure that the column won't have to be converted to the parameter's type. Here Datetime is higher than Date, so no explicit conversion on the parameter is needed.
Next, start with the a single useful clustered index, perhaps (CampaignId,CallDateTime). This will give you an optimal plan for the first query and a reasonable plan for the second query.
If you have millions of rows and lots of different reporting queries that would require many different indexes for optimal performance, consider adding a non-clustered or clustered columnstore index . This switches to columnar storage with the highest compression and fastest scan rate. With a columnstore you don't need the perfect index for each reporting query because scanning a few million rows in a columnstore is really fast.
fafcakar2#
To create a good index for one query:
=
where CampaignId = @CampaignId and CallDateTime >= @Date and CallDateTime < dateadd(day,1,@Date)
As David pointed out, making the tests Sargable is important. Then
For this:
have
Neither index is very useful for the other query. Make the optimal index for each query, then see if some indexes are the same or similar enough.
For example:
INDEX(a,b,c)
will work fine for a query that needsINDEX(a,b)