Oracle 为稀疏列定义索引
我有一个列为“a”和“B”的表 “A”是一个包含90%的“null”和10%不同值的列,大多数情况下,我会查询包含一个或两个不同值的记录 “B”是一个列,其中90%的值为1,10%的值不同,大多数情况下,我查询的记录中都有一个或两个不同的值 在这个表中,我们大部分时间都有DML事务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_b_idx(按该顺序):
- a) 选择。。。从…起其中A=。。。将使用索引
- b) 选择。。。从…起其中B=。。。不会使用索引
- a) 选择。。。从…起其中A=。。。不会使用索引
- b) 选择。。。从…起其中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列
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栏
Q3: select * from MyTable where B = 1;
但它将有助于实现不同的价值观
Q4: select * from MyTable where B = '456';
- 空值
- 确保您的DBMS版本支持索引中包含的空值。例如,Oracle11g没有,但没有之前的版本
- 计划再次与Oracle一起创建基于函数的索引。但你至少可以接受这个想法
- 重新设计应用程序的逻辑/需要查询空值。我更喜欢这种方法。
x(a)
上的索引将只包含非空值。@WernfriedDomscheit由多个sessions@a_horse_with_no_name这意味着空值的存在不会对oracle造成任何影响?非常感谢。但是你的回答和我的问题有关吗@AlexanderAnikin-Oracle已经有相当一段时间进行索引跳过扫描了,所以答案的最初部分不再是这样。看看基于函数的索引,比如createindex。。。在…上(nvl(A,'XX')“代码>将是无用的(即浪费空间),因为Oracle optimizer无论如何都会跳过此类索引。@WernfriedDomscheit,您完全正确,但并非完全正确。”。您可以强制优化器将基于函数的索引包含到查询计划中,或者在查询中适当地使用基于函数的索引。在这种情况下,索引确实很有用。是的,但是扫描索引以查找占所有值90%的值是浪费时间的。>重新设计应用程序的逻辑/您需要执行查询