加速SQL到Linq ToList

时间:2011-09-25 18:23:49

标签: c# sql linq linq-to-sql .net-4.0

我有一个大约有380,000行的SQL表。

在SQL SMSS中,我执行此查询:

 SELECT Longitude, Latitude, street FROM [Stops].[dbo].[Members]   
 WHERE ABS(Latitude - 51.463419) < 0.005 AND ABS(Longitude - 0.099) < 0.005 

它几乎立即返回大约20个结果。

我有一个WCF webserice将我的数据暴露给我的Windows手机应用程序:

public class Service1 : IService1
{
    double curLatitude = 51.463;
    double curLongitude = 0.099;

    public List<Member> GetMembers()
    {
        DataClassesDataContext db = new DataClassesDataContext();
        var members = from member in db.Members                            
where (Convert.ToDouble(member.Latitude) - curLatitude) < 0.005 && (Convert.ToDouble(member.Longitude) - curLongitude) < 0.005

select member;
        return members.ToList();
    }
}

我相信它正在执行相同的查询,但也将项目添加到List。

问题是,需要7分钟以上才能得到一些奇怪的异常,所以永远不会完成。 VS2010中的WCF服务测试程序只是填充内存并在执行此操作时使用大量CPU。 我的感觉是ToList做了一些奇怪的事情?

2 个答案:

答案 0 :(得分:3)

您缺少LINQ版本中的abs部分。

一些旁注。
您可以至少以两种可能的方式跟踪SQL查询。

  1. 使用SQL事件探查器并在那里检查查询(然后您可以在SQL Management Studio中粘贴查询并将输出与上面的查询进行比较)。
  2. 插入db.Log = Console.Out;(或其他TextWriter)并检查Visual Studio中的输出窗口。
  3. 你应该处理你的DataClassesDataContext,最好的方法是将它放在一个使用块中:

    public List<Member> GetMembers()
    {
        using(DataClassesDataContext db = new DataClassesDataContext())
        {
            var members = from member in db.Members                            
            where (Convert.ToDouble(member.Latitude) - curLatitude) < 0.005
                && (Convert.ToDouble(member.Longitude) - curLongitude) < 0.005
            select member;
            return members.ToList();
        }
    }
    

答案 1 :(得分:2)

这里有很多问题:

  • (编辑:忽略这一点;我误读了380,000作为被提取的数据),这是一个非常大量的数据来查询和引入网络;例如,查询分析器需要多长时间?
  • 至少需要很长时间
  • 将其加载到LINQ-to-SQL中时,您会遇到物化开销和身份管理器开销;后者可以通过禁用数据上下文的对象跟踪来解决;前者比较棘手 - 如果你怀疑这很重要(可能有时候),或许像“小精灵”这样的东西可以加载它(它有更高效的物质供应者,并且不包括身份管理员)
  • WCF必须序列化这些数据,这可能需要相当多的CPU和内存 - 然后需要通过网络(带来带宽)。如果您可以自由更改格式,其他序列化程序可能会在此处保存CPU和带宽。

因此;首先要做的是确定时间的去向。

  • 我首先从查询分析器运行它;也许索引丢失了?
  • 将ObjectTrackingEnabled设置为false
  • 之后,将数据访问与WCF分开以查看哪个是罪魁祸首 - 时间只是数据到列表的步骤
  • 之后,时间DataContractSerializer将这些数据序列化并测量序列化时的数据大小(个人而言,我将与protobuf-net进行比较 - 但这可能不是一个选项,具体取决于您的情况)
  • 然后测量网络上的时间

任何或所有这些都可能需要在此进行优化。