【问题标题】:Indexing vs. no indexing when inserting records插入记录时索引与不索引
【发布时间】:2010-09-19 11:47:03
【问题描述】:

我有几个关于不使用索引是否最好的问题。

背景: 我的记录有时间戳属性,记录会按照时间戳的顺序插入(即按时间顺序插入)。

问题:

  1. 如果我不使用索引,数据库是否通常按照插入的顺序插入记录?

  2. 如果对 #1 的回答是肯定的,那么当我执行“SELECT .. WHERE timestamp > X”类型查询时,数据库是否会有效,或者它是否必须遍历每条记录,因为它不是没有索引?我假设如果没有索引,数据库将不会“知道”记录是按排序顺序插入的,因此无法使用数据库的排序属性。

我认为聚集索引最适合这些类型的记录及其插入。

请让我知道你们的想法。

谢谢, jbu

【问题讨论】:

  • “聚集索引”是一个特定于 sybase 和 sql server 的术语,我认为,所以这个问题几乎肯定与 sql server 有关。

标签: database sorting clustered-index


【解决方案1】:

根据我的经验,是的,数据库会按时间顺序插入内容,尤其是在您从不删除任何内容的情况下。但是,这并不能保证,并且尝试依赖无法保证的行为是一个非常糟糕的主意。

此外,查询规划器不会知道这一事实,因此您在没有索引的情况下执行的任何查询都会导致全表扫描。这是否比索引查询慢在很大程度上取决于您拥有的数据类型以及查询中“X”之后的百分比。

【讨论】:

    【解决方案2】:

    当然,这取决于您使用的数据库!

    一般来说,如果您有很多插入操作,最好禁用索引,执行插入,然后重新创建索引

    使用时间戳作为聚集索引(即存储行的顺序)只有在您最常见的查询是按时间顺序(而不是检索此行)并且没有重复的时间戳时才有意义

    【讨论】:

    • 史蒂文,我已经发布了对此答案的跟进作为另一个答案,因为我在此评论中没有空间回复。
    【解决方案3】:

    如果表中从未有任何删除,您可以假设数据库将简单地将新块添加到表的末尾。但是,无法保证磁盘上的这些块是否连续,甚至是否正确推进(即,随着时间的推移,表很可能会被碎片化)。

    来自没有索引的表的任何 SELECT 都将导致表扫描。索引是您“告诉”数据库“时间戳按升序排列”之类的方式。

    聚集索引有助于告诉数据库您希望在表中保持行的索引顺序。但是,它通常(取决于您的实现)仅对合理的静态数据有价值,因为这是数据库确保表的行确实按索引顺序排列的唯一方法,就像它通过重建表一样。

    【讨论】:

    • 聚集索引最初将填充页面的 x% - 留下 100-x% 用于插入。只有在插入溢出的记录时,才需要进行页面拆分和部分“重建”。 (请注意,我专门说的是 MSSQL Server,但如果它在其他 RDBMS 中不相似,我会感到惊讶)
    【解决方案4】:

    什么数据库?

    1)
    没有索引的表称为堆。堆将按照插入的顺序存储记录。只要您不从多个线程插入,您就可以预测数据库存储记录的顺序。正如其他人指出的那样,这确实假定您不进行删除,在这种情况下您的 DBMS 可能用新行填充空白页。

    2)
    如果没有索引,DBMS 将不得不进行完整的表扫描(它以与记录数相关的线性时间运行)。对于插入时间戳增加的记录的记录,聚集索引会很好。只要您不插入旧的时间戳,DBMS 就必须由于聚集索引而物理地重新排列行。

    【讨论】:

      【解决方案5】:

      聚集索引是记录在磁盘上的存在顺序。不管你是否指定,总会有一个,因为磁盘上必须有一个订单。

      主键也是聚集索引是正常的,但不一定是这种情况。

      如果您正在执行批量插入,您可能会插入多个具有相同时间戳的记录。显然这不能是主键。

      为了执行像“SELECT .. WHERE timestamp > X”这样的查询,“timestamp”字段上的索引将提高该查询的性能,无论它是否是集群的。

      'timestamp' 字段上的索引是否应该聚集以及是否还需要其他索引将取决于您需要对数据执行的所有查询。

      【讨论】:

        【解决方案6】:

        我是帖子创建者 jbu。

        感谢大家的快速输入。

        解决更多问题:

        是的,我有静态数据 - 我不会删除。

        我正在测试几个不同的数据库:Sybase SQL Anywhere、Oracle Berkeley DB、H2、Firebird、SQLite,可能还有其他一些。

        致 Steven Lowe:我的表将有数百万条记录(最多会增长到 32GB)。如果我关闭索引一段时间,然后重新创建索引,那会不会需要很长时间 - 至少几分钟(我会假设它可能需要更长的时间)?另外,我认为您假设插入的连续流动将会中断。我几乎会一直使用批量插入提交进行插入,所以我认为我的 CPU 和磁盘不会真正有休息时间来重新索引。

        再次感谢大家的意见。

        Jbu

        【讨论】:

        • 您的尺码不一致;如果您从不删除,随着时间的推移,您的数据将增长到超过 32 GB。虽然你可能在小尺寸上还可以,但没有索引可能会在大尺寸上削弱你。
        • 请注意,您可以编辑原始问题以添加此类澄清信息,而不是发布答案;这也“刷新”了活动选项卡上的问题,以便更多人看到它
        • @Steven - 我认为你需要比 jbu 更多的代表来编辑你的问题。
        【解决方案7】:

        这是典型的,但任何特定的实现都不能保证,AFAIK。因此,依赖它是不明智的。查询优化器也不依赖它,所以它会进行表扫描。

        在您的情况下,时间戳上的聚集索引确实没有缺点。你可以填满 100% 的数据页,但你仍然不会比堆更糟。然而,查询可以利用它,并且可以从略微(如果您返回,例如,90% 的表格)到可笑(如果您要返回,例如,1% 的表格)更快.

        【讨论】:

          【解决方案8】:

          我相信根据 sql 标准,您永远无法确定在非有序列中选择行的顺序。即使您测试给定的数据库并发现它当前是正确的,但在数据库的下一个版本中可能并非如此。我的经验秒 Steven Lowe's。如果要在表中插入大量行,请在插入之前禁用(或删除)这些行。插入后重新创建索引将比打开索引的插入花费更少的时间。

          艾伦

          【讨论】:

          • 但是,对于一个拥有数百万条记录(可能至少有 1 亿条)的数据库,重新索引将需要很长时间,不是吗? -jbu
          【解决方案9】:

          您需要在时间戳列上创建索引才能搜索我的时间戳。随心所欲 (TM)。

          只有在您按主键搜索时,聚集索引才对您有所帮助。您可以将时间戳作为主键来利用它。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-12-03
            • 1970-01-01
            • 2017-01-16
            • 2017-04-04
            • 1970-01-01
            • 2012-02-18
            • 2016-01-09
            相关资源
            最近更新 更多