【问题标题】:How to maximize performance?如何最大化性能?
【发布时间】:2012-02-06 11:36:09
【问题描述】:

我有一个问题,无论我怎么努力,我似乎​​都无法解决。

这家公司从事市场分析工作,拥有非常大的表格(300K - 1M 行)和许多列(想想 250-300),我们对其进行了一些计算。

我会尝试直接解决问题:

问题在于数据的过滤。到目前为止,我尝试过的所有数据库都太慢了,无法选择数据并返回。

目前我将整个表存储在内存中并使用动态 LINQ 进行过滤。

但是,虽然这相当快(过滤 250 000 行大约需要 100 毫秒),但我需要比这更好的结果...

有什么方法可以更改我的代码(不是数据模型)中的某些内容,从而加快过滤速度?

我尝试过使用:

DataTable.Select 慢的。动态 LINQ 哪个更好,但是 还是太慢了。普通 LINQ(仅用于测试目的)几乎 已经足够好了。从 MySQL 中获取并稍后进行处理 这太慢了。

在这个项目的开始,我们认为一些高性能的数据库可以处理这个,但我尝试了:

H2 (IKVM) HSQLDB(编译的 ODBC 驱动程序) 多维数据集SQL MySQL SQL SQLite ...

而且它们在连接 .NET 和从中获取结果时都很慢。

我还尝试将数据拆分成块,然后在运行时将它们组合起来,以使需要过滤的数据总量更小。

在这个宇宙中有没有什么方法可以让我更快?

提前致谢!

更新

我只想补充一点,我没有创建有问题的数据库。

要添加一些数字,如果我像这样在数据库查询窗口 (SQLyog) 中简单地选择 2 个字段(visit_munic_name 已编入索引):

SELECT key1, key2 FROM table1 WHERE filter1 = filterValue1

225639 行需要 125 毫秒。

为什么这么慢?我已经测试了 2 个不同的盒子。

当然他们必须改变一些东西,很明显?

【问题讨论】:

  • 说实话,这并不是很多行。在我看来,数据库结构需要认真对待。
  • 您是否检查过使用 DB 时慢的原因 - 网络请求本身或 DB 端的 SQL 查询执行?如果网络请求/响应很慢 - 看看你是否可以将数据库托管在靠近应用程序的地方,否则调整 sql 查询性能、表索引等
  • 您说使用您使用的所有数据库选择数据都很慢。这在我心中提出了几个危险信号。您是否在选择中进行任何复杂的连接?你有复杂的where子句吗?您的数据库是否正确编入索引?
  • 那么索引呢?它是否覆盖过滤器列?过滤器列是索引中的第一个还是您创建了一个包含 XX 列的索引?查询第一列是过滤器并包含选择值的索引甚至不应该是可测量的 - 除非过滤器返回大量记录,在这种情况下你不能真正责怪数据库。查询返回多少条记录?您的查询应尽可能有选择性,否则使用数据库没有多大意义
  • 您要过滤的列似乎没有建立索引,或者如果是,则可能是索引高度碎片化。您可以通过运行 DBCC SHOWCONTIG 命令来验证这一点。我会尝试 DBCC SHOWCONTIG('tablename') 作为起点。有关更多选项,请参阅bit.ly/AsNWRE

标签: c# database performance linq dynamic-linq


【解决方案1】:

你没有解释你到底想做什么,或者为什么过滤很多行很重要。如果您的数据库可以为您预先计算聚合,那么过滤 1M 行以获得聚合的速度又何必重要呢?无论如何,您似乎使用了错误的工具来完成这项工作。

一方面,对于大多数数据库来说,1M 行只是一小部分行。只要您有正确的索引,查询应该不是一个大问题。我怀疑您的查询列上没有索引,或者您想对非索引列执行临时查询。

此外,如果您的数据架构不适合这项工作,您使用哪个数据库都没有关系。分析应用程序通常使用星型模式来允许对比您描述的更多的数据进行更快的查询。

所有用于分析目的的数据库都使用特殊的数据结构,要求您将数据转换为他们喜欢的形式。 对于典型的关系数据库,您必须创建与多维数据集相结合的星型模式以预先计算聚合。 列数据库以列格式存储数据,通常结合压缩来实现快速分析查询,但它们要求您学习用他们自己的语言查询它们,这可能与大多数人习惯的 SQL 语言有很大不同。

另一方面,您的查询方式(LINQ 或 DataTable.Select 或其他)对性能的影响很小。选择正确的数据结构更为重要。

例如,使用 Dictionary 比使用您提到的任何技术都要快得多。字典本质上检查内存中的单个值。在没有索引的情况下执行 DataTable.Select,使用 LINQ to Datasets 或 to Objects 本质上与扫描数组或 List 的所有条目以获取特定值相同,因为这就是所有这些方法的作用 - 按顺序扫描整个列表。

各种 LINQ 提供程序不做数据库的工作。它们不会优化您的查询。他们只是执行您告诉他们执行的操作。即使在排序列表上进行二进制搜索也比使用通用 LINQ 提供程序更快。

您可以尝试多种方法,具体取决于您需要做什么:

  • 如果您正在寻找一种对数据进行切片和切块的快速方法,请使用现有产品,例如 Excel 2010 的 PowerPivot 功能。PowerPivot 以内存中的列格式加载和压缩数百万行,并允许您查询您的数据。数据就像使用数据透视表一样,甚至可以定义与其他内存源的连接。
  • 如果您想要一个更可重复的过程,您可以在关系数据库中创建适当的星型模式或使用列式数据库。无论哪种情况,您都必须编写脚本以正确的结构加载数据。

  • 如果您要创建自己的应用程序,您确实需要研究其他类似工具在内存中使用的各种算法和结构。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-30
    • 2012-06-15
    • 1970-01-01
    • 2011-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-25
    相关资源
    最近更新 更多