Tenho duas tabelas nas quais armazeno:
- um intervalo de IP - tabela de pesquisa de país
- uma lista de solicitações provenientes de diferentes IPs
Os IPs foram armazenados como bigint
s para melhorar o desempenho da pesquisa.
Esta é a estrutura da tabela:
create table [dbo].[ip2country](
[begin_ip] [varchar](15) NOT NULL,
[end_ip] [varchar](15) NOT NULL,
[begin_num] [bigint] NOT NULL,
[end_num] [bigint] NOT NULL,
[IDCountry] [int] NULL,
constraint [PK_ip2country] PRIMARY KEY CLUSTERED
(
[begin_num] ASC,
[end_num] ASC
)
)
create table Request(
Id int identity primary key,
[Date] datetime,
IP bigint,
CategoryId int
)
Desejo obter o detalhamento da solicitação por país, para isso realizo a seguinte consulta:
select
ic.IDCountry,
count(r.Id) as CountryCount
from Request r
left join ip2country ic
on r.IP between ic.begin_num and ic.end_num
where r.CategoryId = 1
group by ic.IDCountry
Tenho muitos registros nas tabelas: cerca de 200.000 em IP2Country
e alguns milhões em Request
, então a consulta demora um pouco.
Observando o plano de execução, a parte mais cara é uma busca de índice clusterizado no índice PK_IP2Country, que é executado várias vezes (o número de linhas na solicitação).
Além disso, algo que me parece um pouco estranho é a left join ip2country ic on r.IP between ic.begin_num and ic.end_num
parte (não sei se existe uma maneira melhor de realizar a pesquisa).
A estrutura da tabela, alguns dados de exemplo e consulta estão disponíveis no SQLFiddle: http://www.sqlfiddle.com/#!3/a463e/3 (infelizmente acho que não consigo inserir muitos registros para reproduzir o problema, mas isso espero que dê uma ideia).
Eu (obviamente) não sou um especialista em desempenho/otimizações de SQL, então minha pergunta é: há alguma maneira óbvia de melhorar o desempenho dessa estrutura/consulta que estou perdendo?