Database 在列和唯一列上创建索引的最佳候选项是什么?

Database 在列和唯一列上创建索引的最佳候选项是什么?,database,oracle,database-design,Database,Oracle,Database Design,我总是问自己,我是否应该在Oracle表中创建索引,表中的哪些条件使索引值得创建?这也是查询中的一个条件吗?(对于Oracle)是否有基于某些因素可以创建的不同类型的索引?关键在于对表运行什么查询,查询速度有多快,需要多快,以及运行频率有多高。如果您需要基于它快速查找记录,请为其编制索引。您的查询 您必须查看或更好地分析您的客户端应用程序代码,以查看哪些字段最常使用和/或存在性能问题。如果您的应用程序尚未构建,请考虑如何使用数据。例如;如果这是一个将大量用于报表的表,并且您有一个datetime

我总是问自己,我是否应该在Oracle表中创建索引,表中的哪些条件使索引值得创建?这也是查询中的一个条件吗?(对于Oracle)是否有基于某些因素可以创建的不同类型的索引?

关键在于对表运行什么查询,查询速度有多快,需要多快,以及运行频率有多高。如果您需要基于它快速查找记录,请为其编制索引。

您的查询


您必须查看或更好地分析您的客户端应用程序代码,以查看哪些字段最常使用和/或存在性能问题。如果您的应用程序尚未构建,请考虑如何使用数据。例如;如果这是一个将大量用于报表的表,并且您有一个datetime字段,则很可能需要在该字段上创建索引(复合索引或非复合索引)。

创建唯一约束时,Oracle会自动在列(或列集)上创建唯一索引。索引用于强制执行约束

创建主键约束时,Oracle还会自动在列(或列集)上创建唯一索引。此索引也用于强制执行约束。主键约束和唯一约束之间几乎没有区别,但有些区别

此外,当一列(或一组列)经常用于联接一对表时,应该指定外键关系。为此,被引用的列必须是被引用表上的主键,这反过来意味着该被引用表上将有一个唯一的(主键)索引

此外,当WHERE子句中经常使用特定列(或一组列)时,创建索引(unique或其他)是有意义的。具有极低基数(相对于总行数的唯一值数量较少)的列,位图索引可能是有利的。位图索引的利弊可能是一个漫长的讨论

应仔细考虑多列索引中列的顺序。首先,多列索引与同一列上的单个单列索引完全不同,但Oracle很少(如果有的话,尤其是在没有任何提示的情况下)在单个查询上使用多个索引(位图索引可能是一个例外)。如果WHERE子句中通常有A、B和C列,则可能需要A、B和C上的索引。但是,如果WHERE子句中也经常使用A和C,而不使用B,则可能需要将索引中的列排序为A、C、B。当WHERE子句中只有A时,也可以使用此类索引。简单地说,Oracle只能通过使用索引的前缀而不是索引中列的随机组合来使用索引中列的子集

还需要注意的是,表上的索引越多,写入该表的速度就越慢。只需考虑Oracle必须做的所有工作来更新表和与之相关联的所有索引。位图索引可能会产生更大的影响


最后一点,请说明计划是您的朋友。如果您发现通常在大型表上执行完整表扫描的查询,索引可能是有序的。

经验法则是在外键(PK通常自动创建索引)、连接中涉及的字段、where子句或排序上创建索引。索引有插入的代价,所以不要随意地在所有内容上创建索引。选择使用最频繁的内容和运行时间最长的查询,以查看可能需要索引的位置。检查您的查询执行计划(不同的数据库称之为不同的东西,但都有办法查看查询将如何使用索引),以查看在创建索引后是否正在使用它们。没有使用的索引只是添加到插入和删除时间,而在选择时间中没有相应的导入

完全取决于对表运行的查询

可能的候选人包括:

  • 联接中涉及的字段
  • 作为WHERE子句一部分的字段
  • 字段是订单的一部分
  • 请不要认为这意味着您应该在一个表上创建一大堆索引,每个索引都在一个字段上。我经常看到这一点,而且几乎总是错误的答案。其他一些考虑因素:

    • 考虑复合索引,尤其是覆盖索引
    • 在决定是否应该对字段进行索引,或者在索引中放置字段的顺序时,请考虑字段的选择性

      • 这里有一些好主意。请特别注意有性能问题的查询,并尝试以高选择性创建索引

        顺便说一句,监视索引使用情况并不是一个坏主意:

        ALTER INDEX <index> MONITORING USAGE;
        
        改变索引监控使用;
        
        您可以定期检查v$object_usage.usage的值,以查看在启用监视后是否访问过索引:

        SELECT i.table_name, i.index_name, i.tablespace_name, bytes/1000000 mb, u.used
          FROM dba_indexes i JOIN dba_segments ON (i.index_name = segment_name)
                  LEFT OUTER JOIN v$object_usage u ON (i.index_name = u.index_name)
         WHERE i.owner = <schema>
           AND NVL(USED,'NO') = 'NO'
           AND i.table_name = <table of interest>
         ORDER BY bytes DESC;
        
        选择i.table\u名称、i.index\u名称、i.tablespace\u名称、字节/1000000 mb、u.used
        从dba_索引中,我加入上的dba_段(i.index_name=段名称)
        左外部联接v$object\u用法u ON(i.index\u name=u.index\u name)
        其中i.owner=
        和NVL(已使用,'NO')='NO'
        和i.table_name=
        按字节顺序描述;
        

        我已经能够用它提供的信息删减几个索引。

        +1:不要创建随机索引——索引有很大的成本。根据实际用例创建索引。我的数字表明,缺少所需的单列索引与在每个非位列上创建单列索引的成本相同。