代码之家  ›  专栏  ›  技术社区  ›  pablo

Firebird是否需要手动重新编制索引?

  •  13
  • pablo  · 技术社区  · 17 年前

    我同时使用Firebird embedded和Firebird Server,有时我需要使用以下过程重新索引表:

    CREATE PROCEDURE MAINTENANCE_SELECTIVITY 
    ASDECLARE VARIABLE S VARCHAR(200);
    BEGIN
    FOR select RDB$INDEX_NAME FROM RDB$INDICES INTO :S DO
    BEGIN
    S = 'SET statistics INDEX ' || s || ';';
    EXECUTE STATEMENT :s;
    END
    SUSPEND;
    END
    

    3 回复  |  直到 17 年前
        1
  •  21
  •   Lasse V. Karlsen    17 年前

    首先,让我指出我不是Firebird专家,所以我的回答是基于SQL Server的工作原理。

    在这种情况下,答案既是肯定的,也是否定的。

    索引当然会在SQL Server上更新,因为如果插入新行,该表的所有索引都将包含该行,因此将找到该行。因此,基本上,您不需要为该部分继续重新编制表的索引。这是“不”的部分。

    简单的回答是,随着时间的推移,统计数据逐渐失去正常。它们可能不会恶化到无法使用的程度,但当您重新创建/重新计算它们时,它们会从完美的级别恶化。这就是“是”的部分。

    陈旧统计数据的主要问题是,如果索引中键的分布发生急剧变化,统计数据可能无法立即提取,因此查询优化器将根据其手头的陈旧统计数据提取错误的索引。

    例如,假设您的一个索引具有统计信息,表示键在值空间的一端聚集在一起(例如,int列包含大量0和1)。然后插入很多行,这些行的值使该索引包含分布在整个频谱上的值。

    如果您现在对具有此索引的表执行一个查询,该查询使用另一个表中的联接,在一个选择性较低的列上(也有很多0和1),那么查询优化器可能会推断此索引是好的,因为它将获取同时使用的许多行(它们位于同一数据页上)。

    然而,由于数据发生了变化,它会跳转到整个索引中去寻找相关的片段,因此毕竟不是那么好。

    在重新计算统计信息之后,查询优化器可能会发现这个索引对于这个查询来说是次优的,并选择另一个更适合的索引。

    至于是否有可能让Firebird自己做这件事,我还是如履薄冰,但我怀疑有可能。在SQL Server中,您可以按计划设置执行此操作的维护作业,并且至少应该能够从Windows计划程序启动批处理文件来执行类似操作。

        2
  •  8
  •   Harriv    17 年前

    这不会重新编制索引,而是重新计算索引的权重,优化器使用这些权重来选择最佳索引。除非索引大小变化很大,否则不需要这样做。如果在添加数据之前创建索引,则需要重新计算。

        3
  •  1
  •   Rohit Gupta    11 年前

    我想为更新的firebird更新这个答案。下面是更新的dsql。

    SET TERM ^ ;
    CREATE OR ALTER PROCEDURE NEW_PROCEDURE 
    AS
    DECLARE VARIABLE S VARCHAR(300);
    begin
      FOR select  'SET statistics INDEX ' || RDB$INDEX_NAME || ';' 
      FROM RDB$INDICES 
      WHERE RDB$INDEX_NAME <> 'PRIMARY' INTO :S 
      DO BEGIN
         EXECUTE STATEMENT :s;
      END
    end^
    SET TERM ; ^
    
    GRANT EXECUTE ON PROCEDURE NEW_PROCEDURE TO SYSDBA;