I have the following table:
id | query | update_date | website_id | device | page | impressions | clicks | position | is_brand
---+---------+-------------+------------+---------+---------+-------------+--------+----------+---------
1 | kitchen | 2018-05-01 | 2 | desktop | http... | 11000 | 50 | 3 | 1
2 | table | 2018-05-01 | 2 | desktop | http... | 7000 | 40 | 3 | 0
3 | kitchen | 2018-05-02 | 2 | desktop | http... | 11500 | 55 | 3 | 1
4 | table | 2018-05-02 | 2 | desktop | http... | 7100 | 35 | 3 | 0
In this table I need a procedure that for each unique query gives me the best performing row in regards to clicks for a given time period. This resulted in the following procedure:
create or alter procedure get_best_website_querys
@from as date,
@to as date,
@website_id as int
as
begin
WITH cte
AS (SELECT *
, ROW_NUMBER() OVER (PARTITION BY query ORDER BY clicks DESC) RN
FROM search_console_query
where
update_date >= @from and
update_date <= @to and
website_id = @website_id
)
SELECT cte.id
, cte.query
, cte.update_date
, cte.website_id
, cte.device
, cte.page
, cte.impressions
, cte.clicks
, cte.POSITION
, cte.is_brand
FROM cte
WHERE RN = 1
end;
Now, this works and gives me the correct result. My problem is that this table grows quite large and this query performs rather slowly (> 3 minutes for a year). The query gives the following execution plan:
On the table I have a non-clustered index on clicks
and a clustered one on (website_id, update_date)
.
I would like some input in regards to what would be the best approach to getting this to perform better. Any input would be appreciated.