Sql 使用子查询提高更新查询的性能

Sql 使用子查询提高更新查询的性能,sql,sql-server,database,performance,sql-server-2014,Sql,Sql Server,Database,Performance,Sql Server 2014,我有一个ZipCodes表,其中包含美国和加拿大的邮政编码和相关信息——包括纬度和经度 我有一些记录从一个单独的应用程序插入到一个表中,我无法修改。这些记录缺少纬度和经度数据,因此我想相应地填充这些记录。(在有人问起之前,由于性能原因,在运行时使用ZipCodes表进行连接似乎不是一个选项,这就是为什么我最终选择了现在的位置。) 我有如下所示的查询,该查询将设置为作为计划任务运行,它将更新尚未查找其地理数据的任何记录。这个查询(一次100个)需要大约1m 35秒才能运行 我正在寻找任何和所有的选

我有一个ZipCodes表,其中包含美国和加拿大的邮政编码和相关信息——包括纬度和经度

我有一些记录从一个单独的应用程序插入到一个表中,我无法修改。这些记录缺少纬度和经度数据,因此我想相应地填充这些记录。(在有人问起之前,由于性能原因,在运行时使用ZipCodes表进行连接似乎不是一个选项,这就是为什么我最终选择了现在的位置。)

我有如下所示的查询,该查询将设置为作为计划任务运行,它将更新尚未查找其地理数据的任何记录。这个查询(一次100个)需要大约1m 35秒才能运行

我正在寻找任何和所有的选择,我在这里做什么,这可能会提高性能

我求助于一个预定的任务,因为我担心整个服务器都会因为INSERT而不是INSERT或INSERT后触发器来做同样的事情而崩溃。。。但那是我的偏好。考虑到当前的性能问题,触发器似乎是不可能的

ZipCodes表在CityName和ProvinceAbbr上有一个非聚集索引,还包括PostalCode、Latitude和Longitude列。我已将“允许行锁”和“允许页锁”设置为false。此表中的数据可能每季度更改一次,因此脏读是可以的

如有必要,我可以提供执行计划结果。。。但不确定具体是如何生成复制/粘贴材料的,请给我一个提示=D

ZipCodes表有947172条记录,LoadsAvail表在任何给定时间都有大约38k条记录。。。记录被实时/不断地插入、更新和删除,有时是以更大的批量(我认为一次最多插入20条,通常更像一次插入一两条)

一旦大多数记录都有了地理数据,每分钟更新的记录可能不到100条,但我想知道是否有更好的方法来完成这一切

UPDATE TOP (100)
    LoadsAvail

SET
    coordinatesChecked = 1,
    FromLatitude =  (   SELECT TOP (1) Latitude
                                        FROM ZipCodes AS ZipCodes_1 WITH(NOLOCK)
                                        WHERE (CityName = loadsavail.FromCity) AND (ProvinceAbbr = loadsavail.FromState)
                                    ),
    FromLongitude = (   SELECT TOP (1) Longitude
                                        FROM ZipCodes AS ZipCodes_2 WITH(NOLOCK)
                                        WHERE (CityName = loadsavail.FromCity) AND (ProvinceAbbr = loadsavail.FromState)
                                    ),
    ToLatitude =    (   SELECT TOP (1) Latitude
                                    FROM ZipCodes AS ZipCodes_3 WITH(NOLOCK)
                                    WHERE        (CityName = loadsavail.ToCity) AND (ProvinceAbbr = loadsavail.toState)
                                ),
    ToLongitude =   (   SELECT TOP (1) Longitude
                                    FROM ZipCodes AS ZipCodes_4 WITH(NOLOCK)
                                    WHERE        (CityName = loadsavail.ToCity) AND (ProvinceAbbr = loadsavail.toState)
                                )
WHERE
    coordinatesChecked = 0

您可以使用联接而不是子查询

UPDATE T1
SET T1.coordinatesChecked = 1,
    T1.FromLatitude =  T2.Latitude,
    T1.FromLongitude = T2.Longitude
    T1.ToLatitude =    T3.Latitude,
    T1.ToLongitude =   T3.Longitude
FROM            LoadsAvail AS T1 LEFT JOIN ZipCodes AS T2 ON T1.FromCity = T2.CityName AND T1.FromState = T2.ProvinceAbbr
                                 LEFT JOIN ZipCodes AS T3 ON T1.toCity = T3.CityName AND T1.toState = T3.ProvinceAbbr
WHERE    T1.coordinatesChecked = 0

我就把这个留在这里。是的,我读过。这似乎是NOLOCK的一个非常恰当的用法,NOLOCK是一个用作查找表的表,包含大量数据,可能每一个日历季度更改一次?如果数据没有那么频繁地更改,那么是的,提示可能不会造成任何伤害……但也不太可能有帮助,因为数据不会被锁定。:)理解。。。谢谢如果(CityName,ProvinceAbbr)不是唯一的,则可以从不同的城市获得纬度,而不是经度。您知道吗?如果找到CityName和ProvinceAbbr的多个记录,这会起作用吗?由于它是一个zipcode数据库,通常一个城市/州的组合有多个zipcode。你觉得这个查询会更快吗?是的,我会工作,你可以检查查询执行计划。我认为这种方法比为每一行更新执行4个子查询要好。检查执行计划并给我们反馈是很好的
如果为CityName和ProvinceAbbr找到了多个记录,这是否有效
,但对于所选值没有规则(如果找到多个)没有规则,因为如果找到多个,使用哪一个并不重要。因此,子查询中有前1个。但是,是的,这是工作得更好,更好!是的,任何事情都比执行四个子查询=D好