J'ai deux tables dans lesquelles je stocke:
- une plage d'adresses IP - table de recherche par pays
- une liste de requêtes provenant de différentes IP
Les adresses IP ont été stockées sous forme de bigints pour améliorer les performances de recherche.
Voici la structure du tableau:
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
)
Je souhaite obtenir la répartition des demandes par pays, j'exécute donc la requête suivante:
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
J'ai beaucoup d'enregistrements dans les tableaux: environ 200 000 IP2Countryet quelques millions Request, la requête prend donc un certain temps.
En regardant le plan d'exécution, la partie la plus coûteuse est une recherche d'index cluster sur l'index PK_IP2Country, qui est exécutée plusieurs fois (le nombre de lignes dans la demande).
En outre, quelque chose qui me semble un peu étrange est la left join ip2country ic on r.IP between ic.begin_num and ic.end_numpartie (je ne sais pas s'il existe une meilleure façon d'effectuer la recherche).
La structure de la table, des exemples de données et des requêtes sont disponibles dans SQLFiddle: http://www.sqlfiddle.com/#!3/a463e/3 (malheureusement, je ne pense pas pouvoir insérer de nombreux enregistrements pour reproduire le problème, mais cela donne, espérons-le, une idée).
Je ne suis (évidemment) pas un expert en performances / optimisations SQL, donc ma question est la suivante: y a-t-il des façons évidentes d'améliorer cette structure / requête en termes de performances qui me manquent?
begin_ipet end_ippersistantes, pour éviter que le texte et les chiffres ne se désynchronisent d'une manière ou d'une autre.
ip2country (begin_num, end_num)?
give me the first record that has a begin_num < ip in asc order of begin_num(corrigez-moi si je me trompe) pourrait être valide et améliorer les performances.
begin_num, puis analyse end_numdans cet ensemble et ne trouve qu'un seul enregistrement.
begin_num. Je dois également participerA BETWEEN B AND Cassez souvent, et je suis curieux de savoir s'il existe un moyen d'y parvenir sans les fastidieuses jointures RBAR.