一千萬個為什麽

搜索

TSQL性能 - 在最小值和最大值之間加入值

我有兩個表存儲在其中:

  • IP範圍 - 國家/地區查詢表
  • 來自不同IP的請求列表

IP存儲為 bigint 以提高查找性能。

這是表結構:

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
)

我想獲得每個國家/地區的請求細分,因此我執行以下查詢:

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

我在表中有很多記錄: IP2Country 中大約200,000, Request 中有幾百萬,所以查詢需要一段時間。

查看執行計劃,最昂貴的部分是索引PK_IP2Country上的Clustered Index Seek,它被執行多次(Request中的行數)。

另外,我覺得有點奇怪的是在ic.begin_num和ic.end_num 部分之間的左連接ip2country ic on r.IP(不知道是否有更好的方法來執行查找)。

SQLFiddle中提供了表結構,一些示例數據和查詢: http://www.sqlfiddle .com /#!3/a463e/3 (遺憾的是我不認為我可以插入很多記錄來重現問題,但這有希望給出一個想法)。

我(顯然)不是SQL性能/優化方面的專家,所以我的問題是:是否有任何明顯的方法可以在性能方面改進這種結構/查詢,而我卻缺少?

最佳答案

You need an additional index. In your Fiddle example I added:

CREATE UNIQUE INDEX ix_IP ON Request(CategoryID,IP)

它涵蓋了請求表,並獲取索引查找而不是聚集索引掃描。

看看它是如何改善它並讓我知道。我猜它會幫助很多,因為對該索引的掃描是我肯定不便宜的。

轉載註明原文: TSQL性能 - 在最小值和最大值之間加入值