我有一个使用MS Access数据库(.mdb文件)的C#应用程序。我与网络用户共享我的数据库,以便他们可以使用我的应用程序访问数据库。
当我运行我的应用程序时,在网络数据库上执行查询需要更长的时间,而同一查询在本地计算机上花费的时间更少。
任何人都可以提供有关如何通过网络共享上的Access数据库减少此性能问题的建议吗?
答案 0 :(得分:5)
当然,通过网络访问数据库的查询速度不会像访问本地硬盘驱动器上的数据库的查询一样快。不幸的是,开发人员构建一个在本地运行良好的应用程序是相当普遍的,但一旦在网络上部署就会显着减慢。 (对于任何开发人员而言,情况都是如此,而不仅仅是使用Access数据库的开发人员。)
根据我的经验,使用共享Access数据库执行应用程序性能的三个最重要的事情是:
表扫描是像Access这样的共享文件数据库上的谋杀案。确保在WHERE子句中使用的字段上具有索引,或者用于JOIN表。
为了说明,我在包含一个包含421,184行的表的122 MB .accdb文件上运行以下命令:
cmd.CommandText =
"SELECT COUNT(*) AS n FROM zz_sys_archive " +
"WHERE archived Between #2013-01-01# And #2013-04-01#";
如果[archived]字段没有索引,该命令需要78秒才能执行并生成107 MB的网络流量。
在[archived]字段中添加索引后,该命令需要0.4秒才能执行并生成0.9 MB的网络流量。
(但是,不要疯狂并索引所有因为无关的索引只会降低INSERT和UPDATE操作的速度。)
即使使用适当的索引,设计不良的查询也会导致表扫描并降低应用程序速度。例如,查询
cmd.CommandText =
"SELECT COUNT(*) AS n FROM zz_sys_archive " +
"WHERE Year(archived) = 2013";
不是sargable,这意味着它不能使用[archived]字段上的索引,并且使用与之前相同的结果进行表扫描(约80秒完成)。但是,等效查询
cmd.CommandText =
"SELECT COUNT(*) AS n FROM zz_sys_archive " +
"WHERE archived >= #2013-01-01# AND archived < #2014-01-01#";
花了大约一秒钟来执行。
使用本地数据库,通常很容易只读取整个表并忽略您不想要的内容。通过网络访问数据库会使很多更加昂贵,因此在“只需选择*从哪里”之前,请考虑一下真正所需要的内容。