简体   繁体   English

从元组中获取结果的快速查询

[英]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.另一种选择是确保您在PostcodeAPostcodeBAddressInRecordedDatabse表上有正确的索引,并且变量和字段的数据类型匹配,因此没有隐式数据类型转换。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM