Saya memiliki dua meja tempat saya menyimpan:
- tabel rentang IP - negara pencarian
- daftar permintaan yang berasal dari IP yang berbeda
IP disimpan sebagai bigintuntuk meningkatkan kinerja pencarian.
Ini adalah struktur tabel:
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
)
Saya ingin mendapatkan rincian permintaan per negara, jadi saya melakukan permintaan berikut:
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
Saya memiliki banyak catatan di tabel: sekitar 200.000 IP2Countrydan beberapa juta Request, sehingga permintaan membutuhkan waktu.
Melihat rencana eksekusi, bagian yang paling mahal adalah Pencarian Indeks Clustered pada indeks PK_IP2Country, yang dieksekusi berkali-kali (jumlah baris dalam Permintaan).
Juga, sesuatu yang saya merasa sedikit aneh adalah left join ip2country ic on r.IP between ic.begin_num and ic.end_numbagian (tidak tahu apakah ada cara yang lebih baik untuk melakukan pencarian).
Struktur tabel, beberapa sampel data, dan kueri tersedia dalam SQLFiddle: http://www.sqlfiddle.com/#!3/a463e/3 (sayangnya saya tidak berpikir saya bisa memasukkan banyak catatan untuk mereproduksi masalah, tapi ini semoga memberi ide).
Saya (jelas) bukan ahli dalam kinerja / optimasi SQL, jadi pertanyaan saya adalah: Apakah ada cara yang jelas di mana struktur / kueri ini dapat ditingkatkan berdasarkan kinerja yang saya lewatkan?
begin_ipdan end_ipbertahan kolom terhitung, untuk mencegah kemungkinan teks dan angka keluar dari sinkronisasi entah bagaimana.
ip2country (begin_num, end_num)?
give me the first record that has a begin_num < ip in asc order of begin_num(koreksi saya jika saya salah) dapat menjadi valid dan meningkatkan kinerja.
begin_num, kemudian memindai end_numdalam set itu dan hanya menemukan satu catatan.
begin_num. Saya juga harusA BETWEEN B AND Csering bergabung , dan saya ingin tahu apakah ada cara untuk mencapai ini tanpa bergabung dengan RBAR yang membosankan.