我有一张表格记录两个有效英国邮政编码之间的谷歌/必应之间的距离。在使用系统时,会添加此表,以便下一个距离查询变得更快,而且我不必调用Web服务来在线检索距离。
这是表结构:
OID PostcodeA PostcodeB DistanceMeters DistanceMiles
-------------------- --------- --------- --------------------------------------- ---------------------------------------
1 BR60PS BT248DN 788847 490
2 BR60PS CM201JA 64426 40
3 BR60PS CM82AP 77640 48
4 BR60PS CO123AX 131617 82
5 BR60PS CT146EL 119366 74
6 BR60PS DA110TA 29247 18
7 BR60PS DE216AH 262570 163
8 BR60PS DL81AB 397524 247
9 BR60PS HG27JE 368802 229
10 BR60PS IP121AL 144394 90
11 BR60PS IP141AH 144183 90
12 BR60PS IP209AH 172259 107
现在我有一个通过Linq-to-SQL使用的标量UDF,它的定义如下:
ALTER FUNCTION [dbo].[GetDistanceFromCache]
(@PostcodeA VARCHAR (MAX), @PostcodeB VARCHAR (MAX))
RETURNS DECIMAL
AS
BEGIN
DECLARE @FoundDistance AS DECIMAL;
SELECT @FoundDistance = DistanceMiles
FROM AddressInfoRecordedDistance
WHERE (PostcodeA = @PostcodeA
AND PostcodeB = @PostcodeB)
OR (PostcodeB = @PostcodeA
AND PostcodeA = @PostcodeB);
RETURN ISNULL(@FoundDistance, -1);
END
我需要知道是否有更快的SQL语句或c#linq来获取结果?如果我检索800名员工并针对50个工作运行它们,系统会暂停,如果我没有将DBContext.GetDistanceFromCache()
添加到选择集中,则所花费的时间会大大减少。
这是停滞查询:
var query =
from locum in DbContext.Locums
where
locum.IsActive == true &&
locum.IsAdminMarkedComplete == true &&
locum.IsLocumsExciteBan == false &&
locum.IsGPHCBan == false &&
filterID1.Contains(locum.OID) == false &&
filterID2.Contains(locum.OID) == false
select new {
LocumID = locum.OID,
LocumName = locum.FirstName + " " + locum.LastName,
locum.MobileNumber,
locum.Email,
Gender = locum.Gender ? "Male" : "Female",
locum.DateofBirth,
LocumType = locum.LocumType.Name,
**Distance** = DbContext.GetDistanceFromCache(_Postcode, locum.AddressInfo.Postcode),
Address = String.Format("{0} {1} {2} {3}",
locum.AddressInfo.House.Length == 0 ? String.Empty : locum.AddressInfo.House + ", ",
locum.AddressInfo.Street.Length == 0 ? String.Empty : locum.AddressInfo.Street + ", ",
locum.AddressInfo.Area.Length == 0 ? String.Empty : locum.AddressInfo.Area + ", ",
locum.AddressInfo.Postcode ?? String.Empty),
Postcode = locum.AddressInfo.Postcode,
City = locum.AddressInfo.City.Name,
County = locum.AddressInfo.City.County.Name,
locum.SystemUserID
};
答案 0 :(得分:1)
我认为您的查询很慢,因为每次LINQ查询select new { ... }
时都必须调用DB,这与结果行的次数相同。
在将结果集与之匹配之前,我会从表AddressInfoRecordedDistance
下载数据。我在想这样的事情:
var query = from locum in DbContext.Locums
where ...
select new { ... }; // Don't include GetDistanceFromCache here
var airds = from a in DbContext.AddressInfoRecordedDistance
select a;
foreach (var q in query)
q.Distance = GetDistanceFromCache(q.PostcodeA, q.PostcodeB, airds);
你有它。当然,您还需要GetDistanceFromCache
方法:
// The SQL UDF in C# code here (psuedo code, not tested, just "C blunt")
decimal GetDistanceFromCache(string PostcodeA, string PostcodeB, List<...> table)
{
return (from t in table
where
(t.PostcodeA == PostcodeA && t.PostcodeB == PostcodeB) ||
(t.PostcodeB == PostcodeA && t.PostcodeA == PostcodeB)
select t).FirstOrDefault().DistanceMiles;
}
当然,如果您经常运行上述所有操作,则应缓存变量airds
。
答案 1 :(得分:1)
如果你满足于远程查询的脏读,你可以添加像Nolock这样的表提示。有关详细信息,请参阅MSDN's Table hints。
另一种选择是确保AddressInRecordedDatabse
PostcodeA
表上PostcodeB
和{{1}}以及变量&amp;的数据类型具有适当的索引。字段匹配,因此没有隐式数据类型转换。