网上有很多讨论涉及我的问题,但我没有看到适用于此的模式:
我有一个使用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活动,即使使用修改的查询参数)。
如何刷新操作系统的读缓存以测试我的理论?
答案 0 :(得分: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倍),因为操作系统做了一些魔术,这很难(不可能?)关闭。如上所述添加索引可能会增加删除查询所需的时间。
感谢任何想法或评论!