Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oracle 为稀疏列定义索引_Oracle_Performance_Indexing_Sparse Matrix - Fatal编程技术网

Oracle 为稀疏列定义索引

Oracle 为稀疏列定义索引,oracle,performance,indexing,sparse-matrix,Oracle,Performance,Indexing,Sparse Matrix,我有一个列为“a”和“B”的表 “A”是一个包含90%的“null”和10%不同值的列,大多数情况下,我会查询包含一个或两个不同值的记录 “B”是一个列,其中90%的值为1,10%的值不同,大多数情况下,我查询的记录中都有一个或两个不同的值 在这个表中,我们大部分时间都有DML事务 现在,我不知道在这些列上定义索引是否好?如果是,哪种类型的索引?例如,如果在a、b上有索引a_b_idx(按该顺序): a) 选择。。。从…起其中A=。。。将使用索引 b) 选择。。。从…起其中B=。。。不会使用索

我有一个列为“a”和“B”的表

“A”是一个包含90%的“null”和10%不同值的列,大多数情况下,我会查询包含一个或两个不同值的记录

“B”是一个列,其中90%的值为1,10%的值不同,大多数情况下,我查询的记录中都有一个或两个不同的值

在这个表中,我们大部分时间都有DML事务


现在,我不知道在这些列上定义索引是否好?如果是,哪种类型的索引?

例如,如果在a、b上有索引a_b_idx(按该顺序):

  • a) 选择。。。从…起其中A=。。。将使用索引

  • b) 选择。。。从…起其中B=。。。不会使用索引

另一方面,如果在b上有索引b_a_idx,a:

  • a) 选择。。。从…起其中A=。。。不会使用索引

  • b) 选择。。。从…起其中B=。。。将使用索引

若Oracle不在第一列上进行筛选,它就不能在索引中使用第二列,因为在正常情况下,索引是树状结构:column1->column2->column3->等等

您只需要在列A上建立索引,或者如果您执行类似A)的查询,则需要在列A、B上建立索引

您只需要在B列上建立索引,或者在B、A列上建立索引(如果您执行类似于B的查询)

Oracle不会在索引中存储所有空值,但如果B包含非空值,它可以为A存储空值

有时将整个表读入内存并忽略索引会更有成效。若可能的结果集很大,并且它适用于所有记录,那个么优化器就可以这样做,因为从索引到记录的转换比简单的记录读取成本更高

对于没有统计信息的表,有时也会发生错误,所以您需要使用ALTERTABLE的作业。。。compute statistics或oracle 11+,可以在没有作业的情况下计算这样的统计信息

大多数情况下,另一个索引对于查询是好事,但对于更新/磁盘则是坏事。每个索引占用磁盘空间,每次更新记录都会对每个索引进行更新。因此,对于更新频繁的表来说,拥有许多索引并不好,但对于频繁查询的表来说,最好拥有涵盖所有常见情况的索引

对于大多数平面查询(没有联接/子查询/层次结构),只使用1个索引,因此为每列创建索引通常只是浪费磁盘空间。您需要多列索引来优化A=。。。和B=


至于索引类型,您可能需要简单的非唯一索引。

原则上,位图索引在这种情况下是最好的。然而,由于mulit用户环境的原因,它们并不合适——您可能会通过表锁显著降低应用程序的速度,甚至可能会得到死锁

也许您可以通过智能分区和使用(Oracle 12c中的新功能)来优化应用程序

下面的CREATE TABLE语句应该是等效的

CREATE TABLE YOUR_TABLE (a INTEGER, b INTEGER, ... more COLUMNS)
PARTITION BY LIST (a) SUBPARTITION BY LIST (b) (
    PARTITION part_a_NULL VALUES (NULL) (
        SUBPARTITION part_a_NULL_b_1 VALUES (1) INDEXING OFF,
        SUBPARTITION part_a_NULL_b_other VALUES (DEFAULT) INDEXING ON
    ),
    PARTITION part_a_others VALUES (DEFAULT) (
        SUBPARTITION part_a_others_b_1 VALUES (1) INDEXING OFF,
        SUBPARTITION part_a_others_b_other VALUES (DEFAULT) INDEXING ON
    )   
);

CREATE TABLE YOUR_TABLE (a INTEGER, b INTEGER, ... more COLUMNS)
PARTITION BY LIST (a) SUBPARTITION BY LIST (b) 
    SUBPARTITION TEMPLATE (
        SUBPARTITION b_1 VALUES (1) INDEXING OFF,
        SUBPARTITION b_other VALUES (DEFAULT) INDEXING ON
    )
(
    PARTITION part_a_NULL VALUES (NULL),
    PARTITION part_a_others VALUES (DEFAULT)
);

CREATE INDEX IND_A ON YOUR_TABLE (A) LOCAL INDEXING PARTIAL;
CREATE INDEX IND_B ON YOUR_TABLE (B) LOCAL INDEXING PARTIAL;
这样,索引将只占用整个表空间的10%。如果WHERE条件为
,其中A为NULL
其中B=1
,则Oracle optimizer无论如何都会跳过此类索引

使用此查询进行验证

SELECT table_name, partition_name, subpartition_name, indexing
FROM USER_TAB_SUBPARTITIONS
WHERE table_name = 'YOUR_TABLE';
如果在所需子分区上使用索引

更新

我只是看到,实际上这是一种过度杀伤力,因为列A上的NULL值无论如何都不会创建任何索引项。因此,它可以简化为

CREATE TABLE YOUR_TABLE (a INTEGER, b INTEGER, ... more COLUMNS)
PARTITION BY LIST (b) (
    PARTITION part_b_1 VALUES (1) INDEXING OFF,
    PARTITION part_b_other VALUES (DEFAULT) INDEXING ON
);
  • A列
假设您创建了一个名为_column的索引。一般来说,RDBMS中的索引不包含空值,这意味着_columnA_index_中没有指向具有空值的记录的索引项。因此,下面的查询

Q1: select * from MyTable where A is null;
将导致表扫描(或者DBMS选择在另一列上使用另一个索引,如果有的话)

然而,由于有10%的记录具有“不同的值”,例如,_columnA_index_u当然有助于查询

Q2: select * from MyTable where A = '123';
在上面的示例中,如果查询返回<1%的记录,那么_columnA_index_uu将非常有用。根据查询的选择性,索引可以极大地提高性能。您可以创建适合列A的数据类型的索引

  • B栏
同样,在B上建立索引也不会有帮助

Q3: select * from MyTable where B = 1;
但它将有助于实现不同的价值观

Q4: select * from MyTable where B = '456';
  • 空值
到目前为止,我的回答是,任何索引对空值都没有帮助。因此,如果您大部分时间都需要查询Q1,我建议您使用以下方法

  • 确保您的DBMS版本支持索引中包含的空值。例如,Oracle11g没有,但没有之前的版本

  • 计划再次与Oracle一起创建基于函数的索引。但你至少可以接受这个想法

  • 重新设计应用程序的逻辑/需要查询空值。我更喜欢这种方法。


这些DML是由多个会话完成的还是仅由一个会话完成的?Oracle不会在所有列都为空的情况下索引值。因此
x(a)
上的索引将只包含非空值。@WernfriedDomscheit由多个sessions@a_horse_with_no_name这意味着空值的存在不会对oracle造成任何影响?非常感谢。但是你的回答和我的问题有关吗@AlexanderAnikin-Oracle已经有相当一段时间进行索引跳过扫描了,所以答案的最初部分不再是这样。看看基于函数的索引,比如
createindex。。。在…上(nvl(A,'XX')将是无用的(即浪费空间),因为Oracle optimizer无论如何都会跳过此类索引。@WernfriedDomscheit,您完全正确,但并非完全正确。”。您可以强制优化器将基于函数的索引包含到查询计划中,或者在查询中适当地使用基于函数的索引。在这种情况下,索引确实很有用。是的,但是扫描索引以查找占所有值90%的值是浪费时间的。>重新设计应用程序的逻辑/您需要执行查询