【问题标题】:MS Access: index optimisationMS Access:索引优化
【发布时间】:2010-12-28 01:24:48
【问题描述】:

假设我们有一个 [Valuations] 表,其中包含每个日期和每个基金的多个值:
-FundId
-ValDate
-值1
-值2...

主键显然是 FundId+ValDate。
我还索引了 ValDate 字段,因为我经常查询特定日期的值。

我的问题是:我应该也为 FundId 创建一个特定的索引,还是 MsAccess 足够聪明以在查询特定 FundId 时使用主键?

【问题讨论】:

    标签: database ms-access database-design ms-access-2007


    【解决方案1】:

    主键显然是 FundId+ValDate

    按什么顺序?您如何访问您的数据?

    Access 数据库引擎使用PRIMARY KEY 作为聚集索引。如果你这样做了

    PRIMARY KEY (FundId, ValDate)

    那么您将在磁盘上获得与执行此操作不同的订单

    PRIMARY KEY (ValDate, FundId)

    要在使用 Access GUI 时显示 PK 中的列顺序(如果您没有使用 SQL DDL 创建PRIMARY KEY):在表设计视图中,单击索引按钮,或在查看菜单。该列表将显示所有索引,对于多个字段,它会显示顺序,您可以更改。

    聚集索引中列的顺序很重要,因为它定义了表的唯一物理索引,即您的 uber 索引。

    (ValDate, FundId) 将偏爱BETWEEN(或等效的)谓词或GROUP BY on ValDate,例如返回多个资金的日期范围查询。

    (FundId, ValDate)可能支持特定的查询...或者可能鼓励页面锁定,具体取决于值的生成方式....

    您现在应该得到的印象是,性能问题涉及许多变量:PK 的定义方式、键值的生成、压缩文件的频率、锁定策略(例如页面级别或行级别?),高或低活动环境等。更不用说您对表运行的查询的性质(例如按日期还是按键?)

    您确定 Access 支持集群 索引?

    当然,这里有一些 MSDN 上的重要文章:

    New Features in Microsoft Jet Version 3.0 “现在压缩数据库会导致索引以聚集索引格式存储。虽然聚集索引直到下一次压缩才会维护,但性能仍然有所提高。这与 Microsoft Jet 2.x 不同,其中存储了数据行输入的方式。新的 clustered-key compact 方法基于表的主键。输入的新数据将按时间顺序排列。"

    Defragment and compact database to improve performance in Microsoft Access “如果表中存在主键,则压缩会将表记录恢复为其主键顺序。这提供了相当于非维护聚集索引,并使 Microsoft Jet 数据库引擎的预读功能更加高效......查询速度将显着提高,因为它们现在正在处理已重写到连续页面中的表的数据。扫描连续页面比扫描碎片页面快得多。”

    How To Optimize Queries in Visual Basic “本文假设您使用的是 Microsoft Jet 数据库引擎...随着您的数据库增长,它会变得碎片化。压缩将表中的所有数据写入硬盘上的连续页面,从而提高顺序扫描的性能。”

    Information about query performance in an Access database “压缩数据库时,可以加快查询速度。压缩数据库时,会重新组织表的记录,以便记录驻留在按表的主键排序的相邻数据库页面中。这提高了对表中的记录进行顺序扫描,因为现在只需读取最少数量的数据库页面即可检索您想要的记录。”

    【讨论】:

    • 感谢这些详细的评论,onedaywhen。但是你确定 Access 支持聚集索引吗?
    • @onedaywhen 重新阅读我的帖子后,我认为您是对的,因为原始引用并未隐式涵盖多列索引。我删除了答案以避免混淆。
    • 很好的链接集合。我曾经在一个 Access 新闻组中因为建议使用随机自动编号作为提高 Jet 数据库中的并发性的一种可能方式而被大喊大叫。想法?
    • (当然,我假设是页面级锁定,而不是记录级锁定)
    • "随机自动编号作为提高 Jet 数据库并发性的一种可能方式......当然,假设是页面级锁定而不是记录级锁定"——我认为这是一个很好的观点还有一个我没有考虑过,直到三年前你说它是一个新闻组(groups.google.co.uk/group/microsoft.public.access/msg/…),请注意我承认这是一个好点。
    【解决方案2】:

    无需在 FundId 列上放置索引。 Access 足够智能,可以在您描述的情况下使用 PK。

    顺便说一句,FundId 是唯一的吗?如果是这样,则无需同时包含 ValDate。

    【讨论】:

    • 这实际上是相当有名的,并且从PK是聚集索引的事实出发,因此按照第一列的顺序编写。但是请记住,如果您在 PK 的第二列和另一个表的 PK 之间定义了关系完整性,Jet/ACE 会创建一个隐藏索引,所以在这种情况下,您不需要创建索引,因为它只会复制 Jet/ACE 为 RI 目的创建的隐藏索引。
    • 无需创建索引,但占用更多空间也无妨。
    • @David W. Fenton:“如果您在 PK 的第二列和另一个表的 PK 之间定义了关系完整性,Jet/ACE 会创建一个隐藏索引”——您应该知道您可以在 ANSI-92 查询模式下通过 SQL DDL 创建FOREIGN KEY 时指定NO INDEX
    • @onedaywhen:那是我不知道的。我一直希望它可以作为 Access UI 中的默认设置关闭,因为我觉得没有在表设计器中显示所有实际索引是错误的。
    • @Tony Toews:我认为最好不要有额外的索引,因为每个表的限制为 32 个。我自己从来没有遇到过这种情况,但我看到过接近的情况。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-05
    • 2014-04-17
    • 2011-09-03
    • 2016-05-18
    • 1970-01-01
    相关资源
    最近更新 更多