我注意到将.ToArray()或.ToList()添加到查询时,数据库查询的运行速度更快。这是因为数据集已加载到内存中,并且所有后续查询都在内存中完成了,而不是进行了更昂贵的数据库调用?
数据库查询的内存存储限制应该是什么,因为我担心占用过多的内部内存会减慢整个项目的速度,因为我确定占用过多的内存存储会大大降低速度。
编辑:这是为Linq SQL查询。我正在使用SQL Server 2008。
示例1:执行大型数据库查询和内存过滤
我有一个包含5000行的数据库表。我查询整个表(例如SELECT * From Clients)。接下来的几个查询基于上一个查询的字段:a)获取所有男性客户;b)获取所有女性客户c)获取FirstName以A开头的所有客户。
示例2:执行更频繁的数据库调用
使用具有5000行的同一个Client表,我需要执行3个查询。b)获取所有女性客户c)获取FirstName以A开头的所有客户。我通过数据库调用而不是在内存中进行所有查询。
哪种方法更有效?
注意:我在查询中使用了一个实体框架“上下文”。答案适用于Entity Framework或LINQ-to-SQL。
ToArray()和ToList()将永远不会加快查询速度。但是,如果您不小心多次运行查询,它们可能会使它以这种方式出现。这是使用LINQ时的常见错误。例如:
// Construct a query to find all the cute puppies
var data = myContext.Puppies.Where(puppy => puppy.Type == PuppyTypes.Cute);
上一行实际上并没有在数据库中查询可爱的小狗。取而代之的是,它构造了一个查询,该查询将在将来某个点查询幼犬。这称为延迟执行。测验问题:上例中的“数据”是什么类型?
当您枚举变量数据时,查询实际上在运行。此变量的类型为IEnumerable。IEnumerables与列表或数组不同。IEnumerable只是可以获取数据的保证。这并不意味着您实际拥有数据。
// Display the puppies
foreach (Puppy p in data) { Console.WriteLine(p.Name); }
上面的foreach调用将强制执行查询。幼犬会出现在屏幕上,但不会缓存在任何位置的阵列或列表中。所以现在,如果您这样做:
// Display their owner's names
foreach (Puppy p in data) { Console.Writeline(p.OwnerName); }
此foreach导致查询再次执行。实际上,如果在两次调用之间在数据库中添加或删除了新的小狗,您甚至可能会得到不同的结果!因此,假设相反,我们将ToList()添加到了初始调用中。
// Construct a query to find all the cute puppies
var data = myContext.Puppies.Where(puppy => puppy.Type == PuppyTypes.Cute).ToList();
现在,数据的类型为List。在幕后,这将创建IEnumerable,然后对其进行foreach,并将结果放入列表中。因此,现在,如果显示小狗的名称和所有者,它将不会两次查询数据库。相反,它遍历列表两次。
如果您搜索“延迟执行”,您会发现许多有趣的用途,以及我列出的警告。通常,您要确保只运行一次查询。如果那需要一个ToList()那就太好了。但是不要不必要地添加ToList()。最后一个例子:
var data = myContext.Puppies.Where(puppy => puppy.Type == PuppyTypes.Cute).ToList();
foreach (Puppy p in data) { Console.WriteLine(p.Name + "," + p.OwnerName); }
你应该在这里有ToList()吗?没有!因为这在您确实不需要列表时会增加列表的开销。更糟糕:
var data = myContext.Puppies.Where(puppy => puppy.Type == PuppyTypes.Cute).ToList();
Console.Writeline(data.Count());
更糟的是!它将所有幼犬拉入内存中的列表,然后对它们进行计数。但是,该查询甚至根本不需要抓住幼犬。这样做:
var data = myContext.Puppies.Where(puppy => puppy.Type == PuppyTypes.Cute);
Console.Writeline(data.Count());
它实际上告诉SQL Server计算幼犬的数量,并且从不浪费带宽或内存,这些幼犬实际上是将幼犬从数据库中加载出来或将其发送到C#或其中的任何一个。
我希望这有帮助!
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句