Please start any new threads on our new
site at https://forums.sqlteam.com. We've got lots of great SQL Server
experts to answer whatever question you can come up with.
| Author |
Topic |
|
ED_KING
Starting Member
7 Posts |
Posted - 2010-04-07 : 18:30:38
|
| Hey guys this query on a very quick SQL server takes about 19 days to complete on the table IP2LocationAllData (6 Million rows)!!I'm kind of stuck.. any ideas? I'm trying to find the nearest lat long to another table with about 2 Million rows of lat and longs for time zone's.--------------------------DECLARE @ipID intDECLARE @Lat floatDECLARE @Long floatDECLARE @cc varchar(2)DECLARE @Location GEOGRAPHYDECLARE IPCursor CURSOR FAST_FORWARD FORSelect ipID, ipLatitude, ipLongitude, countryshortFROM IP2LocationAllData with(nolock) where ipLatitude <> 0 AND ipLongitude <> 0 AND ipTimeZoneID IS NULLOPEN IPCursorFETCH NEXT FROM IPCursorINTO @ipID, @Lat, @Long, @ccWHILE @@FETCH_STATUS = 0 BEGIN SET @Location=GEOGRAPHY::Point(@Lat,@Long,4326) UPDATE IP2LocationAllData SET ipTimeZoneID = ( SELECT TOP 1 TimeZone FROM tblTimeZoneLatLong WITH(INDEX(geoindex1)) WHERE CountryCode = @cc AND Location.STDistance(@Location) < 15000 ORDER BY Location.STDistance(@Location)) WHERE ipID=@ipID FETCH NEXT FROM IPCursor INTO @ipID, @Lat, @Long, @cc ENDCLOSE IPCursorDEALLOCATE IPCursor |
|
|
DBA in the making
Aged Yak Warrior
638 Posts |
Posted - 2010-04-07 : 19:44:35
|
| Try doing it without using a cursor. That's going to cause quite a bottleneck.There are 10 types of people in the world, those that understand binary, and those that don't. |
 |
|
|
ED_KING
Starting Member
7 Posts |
Posted - 2010-04-07 : 23:22:54
|
quote: Originally posted by DBA in the making Try doing it without using a cursor. That's going to cause quite a bottleneck.There are 10 types of people in the world, those that understand binary, and those that don't.
Thanks for the reply. I did it without a cursor and its actually slower.. it seems its not the cursor but the query that tries to figure out the closest lat long to the @location lat and long. Here is my solution without a cursor.DECLARE @i int = 1DECLARE @iRwCnt intDECLARE @ID intDECLARE @ipID intDECLARE @Lat floatDECLARE @Long floatDECLARE @cc varchar(2)DECLARE @ipTimeZoneIDDECLARE @Location GEOGRAPHYCREATE TABLE #TEMP11 (ID int identity(1,1),ipID int,ipLatitude float, ipLongitude float, countryshort varchar(2))INSERT INTO #TEMP11 (ipID, ipLatitude, ipLongitude, countryshort)Select ipID, ipLatitude, ipLongitude, countryshortFROM IP2LocationAllData with(nolock,index(temp1)) where ipLatitude <> 0 AND ipLongitude <> 0 AND ipTimeZoneID IS NULLSET @iRwCnt = @@ROWCOUNTcreate clustered index idx_tmp on #TEMP11(ID) WITH FILLFACTOR = 100 WHILE @i <= @iRwCnt BEGIN SELECT @ID = ID, @ipID = ipID, @Lat = ipLatitude, @Long = ipLongitude, @cc = countryshort FROM #TEMP11 WHERE ID = @i --Do work here SET @Location=GEOGRAPHY::Point(@Lat,@Long,4326) UPDATE IP2LocationAllData SET ipTimeZoneID = ( SELECT TOP 1 TimeZone FROM tblTimeZoneLatLong WITH(INDEX(geoindex1)) WHERE Location.STDistance(@Location) < 25000 ORDER BY Location.STDistance(@Location)) WHERE ipID=@ipID SET @i = @i + 1 ENDDROP TABLE #TEMP11 |
 |
|
|
Asken
Starting Member
38 Posts |
Posted - 2010-04-08 : 01:26:19
|
Well, you didn't actually do it "without a cursor". You just using cursor-like code doing pretty much the same thing. You need'll to use the select from the "select into #TEMP11" as the source for updating IP2LocationAllData to do a batch update without using a cursor. Start off by doing that and then start looking at the query plan. Also make sure that the stats are updated.The clause you should look at is the UPDATE FROM. There are some examples of that at http://msdn.microsoft.com/en-us/library/aa260662(SQL.80).aspx. Reporting & Analysis Specialist |
 |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2010-04-08 : 02:55:24
|
Try thisUPDATE adSET ad.ipTimeZoneID = x.TimeZoneFROM ( SELECT ipTimeZoneID, GEOGRAPHY::Point(ipLatitude, ipLongitude, 4326) AS Location, CountryShort FROM IP2LocationAllData ) AS adCROSS APPLY ( SELECT TOP(1) tz.TimeZone FROM tblTimeZoneLatLong AS tz WITH(INDEX(geoindex1)) WHERE tz.CountryCode = ad.CountryShort AND tz.Location.STDistance(ad.Location) < 15000 ORDER BY tz.Location.STDistance(ad.Location) ) AS x(TimeZone)WHERE ad.ipLatitude <> 0 AND ad.ipLongitude <> 0 AND ad.ipTimeZoneID IS NULL N 56°04'39.26"E 12°55'05.63" |
 |
|
|
ED_KING
Starting Member
7 Posts |
Posted - 2010-04-08 : 16:35:06
|
quote: Originally posted by Peso Try thisUPDATE adSET ad.ipTimeZoneID = x.TimeZoneFROM ( SELECT ipTimeZoneID, GEOGRAPHY::Point(ipLatitude, ipLongitude, 4326) AS Location, CountryShort FROM IP2LocationAllData ) AS adCROSS APPLY ( SELECT TOP(1) tz.TimeZone FROM tblTimeZoneLatLong AS tz WITH(INDEX(geoindex1)) WHERE tz.CountryCode = ad.CountryShort AND tz.Location.STDistance(ad.Location) < 15000 ORDER BY tz.Location.STDistance(ad.Location) ) AS x(TimeZone)WHERE ad.ipLatitude <> 0 AND ad.ipLongitude <> 0 AND ad.ipTimeZoneID IS NULL N 56°04'39.26"E 12°55'05.63"
Okay this looks interesting and i'm going to read up on CROSS APPLY thank you so much you guys.Also i took out the ad.ipLatitude and ad.ipLongitude because their not part of the "AS ad".. i just included the the ipLatitude and ipLongitude <> NULL in the SELECT as ad portion... i'm going to understand it before giving it a shot since this looks promising.cheers! i'll let you know |
 |
|
|
Asken
Starting Member
38 Posts |
Posted - 2010-04-09 : 03:51:36
|
Caution on the cross and outer apply though. Please note that for each row it will apply the cross apply statement. If joins can be used it'll be much faster... not saying it applies to this specific case but as a general note. Reporting & Analysis Specialist |
 |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2010-04-09 : 09:43:20
|
In this case it's justified, since the logic is to get the nearest location [in another table] based on every single entry in source table. N 56°04'39.26"E 12°55'05.63" |
 |
|
|
|
|
|
|
|