[英]Fast query to obtain a result from a tuple
I have a table that records distance from Google/Bing between two valid UK postcodes.我有一张表格,记录了两个有效的英国邮政编码之间与 Google/Bing 的距离。 As the system is used, this table is added to so that the next distance query becomes fast and I do not have to call web services to retrieve distance(s) online.
随着系统的使用,这个表被添加,以便下一个距离查询变得更快,我不必调用 web 服务来在线检索距离。
Here is the table structure:这是表结构:
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
Now I have a Scalar UDF that I use through Linq-to-SQL and it is defined as follows:现在我有一个通过 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
I need to know if there is a any faster SQL statement or c# linq to obtain the result?我需要知道是否有更快的 SQL 语句或 c# linq 以获得结果? If I retrieve 800 employees and run them against 50 jobs, the system goes into a pause and if I don't add the
DBContext.GetDistanceFromCache()
to the set of selects, the time taken is reduced quite significantly.如果我检索 800 名员工并针对 50 个作业运行它们,系统会暂停,如果我不将
DBContext.GetDistanceFromCache()
添加到选择集,则所用时间会大大减少。
And here is the stalling query:这是停滞的查询:
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
};
I think your query is slow because the DB has to be called each time the LINQ query does select new {... }
, which is as many times as you have result rows.我认为您的查询很慢,因为每次 LINQ 查询执行
select new {... }
时都必须调用数据库,这与您的结果行数一样多。
I would download the data from the table AddressInfoRecordedDistance
before matching the result set to it.在将结果集与之匹配之前,我会从表
AddressInfoRecordedDistance
下载数据。 I'm thinking something like this:我在想这样的事情:
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);
And there you have it.你有它。 Of course, you also need the
GetDistanceFromCache
method:当然,你还需要
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;
}
Of course, if you are running all of the above a lot of times, you should cache the variable airds
.当然,如果您多次运行上述所有操作,则应该缓存变量
airds
。
If you're content with dirty-reads for your distance query, you may be able to add table hints like Nolock.如果您对距离查询的脏读感到满意,您可以添加像 Nolock 这样的表提示。 See MSDN's Table hints for more information.
有关详细信息,请参阅MSDN 的表格提示。
Another option would be to ensure you have proper indexes on the AddressInRecordedDatabse
table for PostcodeA
and PostcodeB
and the datatypes of variables & fields match so there are no implicit datatype conversions.另一种选择是确保您在
PostcodeA
和PostcodeB
的AddressInRecordedDatabse
表上有正确的索引,并且变量和字段的数据类型匹配,因此没有隐式数据类型转换。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.