3

在网上进行了许多讨论,涵盖了我的问题的各个方面,但我看不到适用于此的模式:

我有一个使用 EF 3.5 和 MySQL 的基本 .NET WinForm 应用程序。该应用程序适用于大多数查询,但任何包含 Distinct() 的查询都非常慢或导致“在操作完成之前超时时间已过或服务器没有响应”。机器重启后第一次运行时出现异常。即,当重新启动应用程序时,即使在停止并重新启动 MySQL 服务之后,Distinct() 查询从现在开始也可以正常工作(即不到 1 秒)。

我无法通过重新运行应用程序或重新启动 MySQL 来重现问题的事实排除了 EF 编译或 MySQL 缓存是一个因素。只有重新启动后问题再次出现。让我觉得这可能是 .NET 初始化问题或与操作系统相关的其他问题。该问题已在 XP 和 Win 7 上观察到。

任何想法表示赞赏。(还有尝试在不重新启动机器的情况下重现问题的想法,这是非常不切实际的:-)

更新:

EF 生成的查询如下所示:

SELECT Distinct1.C2 FROM (
    SELECT DISTINCT YEAR(Extent1.RecDate) AS C2 
    FROM dailyrecord AS Extent1
    WHERE (Extent1.STN = 430030) AND (Extent1.WBAN = 99999)
) AS Distinct1;

第一次在 mysql shell 中运行大约需要 30 秒,即使在重新启动 mysql 之后,所有后续时间也大约需要 1 秒。重启后回到30s。看起来操作系统第一次读取整个 db 文件,但此后没有(后续查询的 HD 活动很少,即使修改了查询参数)。

如何刷新操作系统的读取缓存以测试我的理论?

4

1 回答 1

1

经过相当多的测试后,出现了这样的情况:

  • 许多查询在 MySQL 和可能(m)任何 DBMS 中的定义非常慢,因为它们需要读取整个数据文件,如上面的“DISTINCT”查询,其中“WHERE”子句包括主键的一部分,但不是整个主键(在本例中是 4 个字段的组合)。

  • 如果慢查询在应用程序中很常见且令人烦恼,则应在搜索条件(“WHERE”字段)上添加索引。这将大大加快查询速度(最终解决了最初发布的问题),但它会增加磁盘上数据的大小(.MYI 文件),同时略微减小 .MYD 文件的大小,但总体上会增加总数据大小。添加索引可能会增加 INSERT、UPDATE 和 DELETE 查询的时间,因为索引也需要更新。 插入大多是在一个接一个的基础上完成的,因此性能损失通常不明显。与批量 DELETE 查询不同(见下文。)

  • 查询的低效率被操作系统掩盖(在我的例子中是 MS Windows XP)。任何需要逐条读取整个表记录的查询在第一次遇到时都非常慢。但是,操作系统将缓存文件,即使参数更改,即使查询本身发生更改,后续查询也会更快:任何需要读取整个表文件的低效查询一旦被操作系统缓存,就会显得很快。这使得调整查询变得困难,因为您需要在测试之间重新启动操作系统。在网上搜索后,我还没有找到一种在 Windows 中刷新读取缓存的实用方法。

  • 一个相关的低效查询是:DELETE FROM myTable WHERE field1 = value。如果有很多记录(在我的情况下为 10,000 条记录需要 30 秒)删除(在所有这些示例中使用 MySQL,存储引擎 MYISAM),即使 field1 上有索引,这也会很慢。这是因为 DBMS 需要从(到)磁盘读取(并且可能写入)整个表文件(取决于 DELETE 的物理执行方式)。同样,这将被操作系统掩盖:第一次很慢,但在随后的查询中非常快(在我的 XP 机器上快 30 倍),因为操作系统做了一些魔法,这很难(不可能?)关闭. 如上所述添加索引可能会增加删除查询所需的时间。

任何想法或意见表示赞赏!

于 2012-11-30T12:55:34.920 回答