我有两个表,Bins和Locations,第一个有300万个记录,第二个有3000万个。我正在尝试将Bin for Location与以下代码匹配
Create Table #tbl_locations (LocationID int not null, Lat float not null, Lon float not null)
Create Table #tbl_bins (BinID int not null, MinLat float not null, MaxLat float not null, MinLon float not null, MaxLon float not null)
CREATE NONCLUSTERED INDEX [IX_tbl_locations] ON [#tbl_locations] ([Lat] ASC, [Lon] ASC)
ON [PRIMARY]
CREATE NONCLUSTERED INDEX [IX_tbl_bins1] ON [#tbl_bins] ([MinLat] ASC, [MaxLat] ASC)
ON [PRIMARY]
CREATE NONCLUSTERED INDEX [IX_tbl_bins2_ABC] ON [#tbl_bins] ([MinLon] ASC, [MaxLon] ASC)
ON [PRIMARY]
Select L.LocationID, C.BinID
From #tbl_bins C
Inner Join #tbl_locations L
ON (L.Lat Between C.MinLat And C.MaxLat)
AND (L.Lon Between C.MinLon And C.MaxLon)
不幸的是性能非常差,我已经尝试索引不同的字段,但这没有用。一切仍然需要超过10分钟才能运行。
任何想法如何让这个表现更好?也许更好的匹配算法? SQL Server 2012 SP3。 BinID和LocationID已经在它们上创建了PRIMARY KEY CLUSTERED。 当我检查执行计划时,我看到JOIN是由NESTED LOOP执行的。
STATISTICS IO的输出是
Table '#tbl_locations_________________________________________________________________________________________________________000000000283'.
Scan count 2631070, logical reads 25575057, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table '#tbl_bins________________________________________________________________________________________________________000000000284'.
Scan count 17, logical reads 14741, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
非常感谢!
编辑 - 如果不是临时表,我使用真实的,这将是导出的模式
/****** Object: Table [dbo].[tbl_Bins] Script Date: 5/30/2017 3:49:05 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[tbl_Bins](
[BinID] [int] NOT NULL,
[MinLat] [float] NOT NULL,
[MaxLat] [float] NOT NULL,
[MinLon] [float] NOT NULL,
[MaxLon] [float] NOT NULL,
CONSTRAINT [PK_tbl_Bins] PRIMARY KEY CLUSTERED
(
[BinID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object: Table [dbo].[tbl_Locations] Script Date: 5/30/2017 3:49:05 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[tbl_Locations](
[ExposureID] [int] NOT NULL,
[Accgrpid] [int] NOT NULL,
[LocID] [int] NOT NULL,
[Lat] [float] NOT NULL,
[Lon] [float] NOT NULL,
CONSTRAINT [PK_tbl_locations] PRIMARY KEY CLUSTERED
(
[ExposureID] ASC,
[Accgrpid] ASC,
[LocID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object: Index [IX_tbl_bins1] Script Date: 5/30/2017 3:49:05 PM ******/
CREATE NONCLUSTERED INDEX [IX_tbl_bins1] ON [dbo].[tbl_Bins]
(
[MinLat] ASC,
[MaxLat] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
/****** Object: Index [IX_tbl_bins2_ABC] Script Date: 5/30/2017 3:49:05 PM ******/
CREATE NONCLUSTERED INDEX [IX_tbl_bins2_ABC] ON [dbo].[tbl_Bins]
(
[MinLon] ASC,
[MaxLon] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
/****** Object: Index [IX_tbl_locations] Script Date: 5/30/2017 3:49:05 PM ******/
CREATE NONCLUSTERED INDEX [IX_tbl_locations] ON [dbo].[tbl_Locations]
(
[Lat] ASC,
[Lon] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
答案 0 :(得分:0)
我找到了改善这种情况的方法。
SELECT L.LocationID, C.BinID
FROM #tbl_bins C
INNER JOIN #tbl_locations L
ON (L.Lat Between C.MinLat And C.MaxLat)
AND (L.Lon Between C.MinLon And C.MaxLon)
WHERE FLOOR(C.MinLat * 1000 ) <= FLOOR(L.Lat*1000)
AND FLOOR(C.MinLon * 1000 ) <= FLOOR(L.Lon*1000)
AND CEILING(C.MaxLat * 1000 ) >= CEILING(L.Lat*1000)
AND CEILING(C.MaxLon * 1000 ) >= CEILING(L.Lon*1000)
这可以通过减少要加入的Bins数量来帮助查询。
答案 1 :(得分:0)
创建覆盖索引:
@if (session()->has('name'))
{{ session('name') }}
@endif
拥有这样的索引意味着不需要访问该表以便检索CREATE INDEX IX_tbl_lat_long_locations ON [#tbl_locations] (Lat, Lon, LocationID)
。
如果可以,请将其设为LocationID
索引。