加速 SQL 到 Linq ToList

发布于 2024-12-06 07:27:09 字数 980 浏览 0 评论 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 Web 服务将我的数据公开给我的 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();
    }
}

我相信它正在执行相同的查询,但还将项目添加到列表中。

问题是,这需要 7 分钟以上,然后我遇到一些奇怪的异常,所以永远不会完成。 VS2010 中的 WCF 服务测试器在执行此操作时会填满内存并使用大量 CPU。 我的感觉是 ToList 正在做一些奇怪的事情?

I have a SQL table with about 380,000 rows.

In SQL SMSS I perform this query:

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

It returns about 20 results almost instantly.

I have a WCF webserice to expose my Data to my Windows phone application:

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();
    }
}

I beleive it is doing the same query, but also adding the items to a List.

The problem is, is that it takes 7+ minutes then I get some strange exception so never completes. The WCF service tester in VS2010 just fills up with memory and uses lots of CPU when permforming this.
My feeling is that the ToList is doing something odd?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

┊风居住的梦幻卍 2024-12-13 07:27:09

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

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

  1. 使用 SQL 探查器并检查其中的查询(然后您可以将查询粘贴到 SQL Management Studio 中并将输出与上面的查询进行比较)。
  2. 插入 db.Log = Console.Out;(或另一个 TextWriter)并检查 Visual Studio 中的输出窗口。

您应该处置您的 DataClassesDataContext,最好的方法是将其放在 using 块中:

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();
    }
}

You are missing the abs-part in your LINQ version.

Some side notes.
You can track the SQL query in at least two possible ways.

  1. Use SQL profiler and check the query there (then you can paste the query in SQL Management Studio and compare the output to your query above).
  2. Insert db.Log = Console.Out; (or another TextWriter) and check the output window in Visual Studio.

You should dispose your DataClassesDataContext, the best way is to put it in a using block:

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();
    }
}
游魂 2024-12-13 07:27:09

这里有很多问题:(

  • 编辑:忽略这一点;我误读了 380,000 作为正在获取的数据)这是一个非常大的数据量,需要通过网络查询和传输;例如,查询分析器需要多长时间? 当将其加载到 LINQ-to-SQL 中时,在任何地方都至少需要那么长的时间
  • ,您有物化开销和身份管理器开销;后者可以通过禁用数据上下文上的对象跟踪来解决;前者比较棘手 - 如果您怀疑这很重要(有时可能如此),也许像“dapper”之类的东西可以加载它(它有一个更高效的物化器,并且不包括身份管理器)
  • WCF必须序列化它数据,这可能需要大量的 CPU 和内存 - 然后需要通过网络传输(这需要带宽)。如果您可以随意更改格式,其他串行器可能会在此处节省 CPU 和带宽。

所以;首先要做的就是确定时间都花在哪里了。

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

任何或所有这些可能这里需要优化。

There are a number of issues here:

  • (edit: ignore this point; I misread the 380,000 as being the data being fetched) that is a very large volume of data to query and bring over the network; how long, for example, does it take in Query Analyzer? It will take at least that long anywhere
  • when loading that into LINQ-to-SQL you have materialisation overheads, and the identity-manager overhead; the latter can be solved by disabling object tracking on the data-context; the former is trickier - if you suspect this is significant (it can be, sometimes) maybe something like "dapper" can load this instead (it has a far more efficient materialiser, and does not include an identity manager)
  • WCF has to serialize this data, which can take quite a lot of CPU and memory - it then needs to come over the network (which takes bandwidth). If you are free to change the format, other serializers might save both CPU and bandwidth here.

So; the first thing to do is identify where the time is going.

  • I would start by running it from Query Analyser; maybe an index is missing?
  • set ObjectTrackingEnabled to false
  • after that, separate the data-access from WCF to see which is the culprit - time just the data-to-a-list step
  • after that, time DataContractSerializer serialising this data and measure the size of the data when serialized (personally, I'd then compare to protobuf-net - but that might not be an option, depending on your scenario)
  • an then measure the time on the network

Any or all of those might need optimising here.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文