往期回顾
Oracle数据库设计规范篇{二}——物理设计规范【上】(基本规范、表设计规范)
Oracle数据库设计规范篇{三}——物理设计规范【中】(分区设计规范)
Oracle数据库设计规范篇{四}——物理设计规范【下】(列的设计,命名的规范)
分区表建立分区索引后,如果在查询应用中无法用到这个分区索引列的条件,索引读将可能遍历所有的分区,如果有100个分区,相当于遍历了100个小索引,将会严重影响性能,此时需要慎重考虑,判断是否需要修改为全局索引。
-- 创建分区表
CREATE TABLE SALES_HISTORY (
SALE_ID NUMBER(10),
CUSTOMER_ID NUMBER(10),
SALE_DATE DATE,
AMOUNT NUMBER(10,2)
)
PARTITION BY RANGE (SALE_DATE) (
PARTITION SALES_Q1_2023 VALUES LESS THAN (TO_DATE('01-APR-2023', 'DD-MON-YYYY')),
PARTITION SALES_Q2_2023 VALUES LESS THAN (TO_DATE('01-JUL-2023', 'DD-MON-YYYY')),
PARTITION SALES_Q3_2023 VALUES LESS THAN (TO_DATE('01-OCT-2023', 'DD-MON-YYYY')),
PARTITION SALES_Q4_2023 VALUES LESS THAN (TO_DATE('01-JAN-2024', 'DD-MON-YYYY'))
);
-- 如果创建局部索引但查询中不使用分区键条件,则不建议
CREATE INDEX SALES_CUST_IDX ON SALES_HISTORY (CUSTOMER_ID) LOCAL;
-- 当执行以下查询时,会扫描所有分区索引
SELECT * FROM SALES_HISTORY WHERE CUSTOMER_ID = 1001;
-- 建议:如果CUSTOMER_ID经常用于查询而不带SALE_DATE条件,应该使用全局索引
CREATE INDEX SALES_CUST_IDX_GLOBAL ON SALES_HISTORY (CUSTOMER_ID) GLOBAL;
从实际应用情况来分析,应用函数索引大多是因为设计阶段考虑步骤,比如trunc(时间列)的写法,往往可以轻易转换成去掉trunc的写法,所以需要取出验证,如下:
select t.index_name,
t.index_type,
t.status,
t.blevel,
t.leaf_blocks
from user_indexes t
where index_type in ('FUNCTION-BASED NORMAL');
1. 位图索引不适合用在表频繁更新的场合。
2. 位图索引不适合在所在列重复度很低的场合。
因为位图索引的应用比较特殊,使用场合比较少,因此有必要取出系统中的位图索引,进行核对检测,如下:
select
t.index_name,
t.index_type,
t.status,
t.blevel,
t.leaf_blocks
from user_indexes t
where index_type in ('BITMAP');
外键未建索引,将有可能导致两个严重的问题:1.更新相关的表产生死锁;2两表关联查询时性能低下,因此设计中需要谨慎考虑。以下为外键未建索引的表的查找语句,以方便我们分析和确认:
select table_name, constraint_name, cname1 || nvl2(cname2, ',' || cname2, null) || nvl2(cname3, ',' || cname3, null) || nvl2(cname4, ',' || cname4, null) || nvl2(cname5, ',' || cname5, null) || nvl2(cname6, ',' || cname6, null) || nvl2(cname7, ',' || cname7, null) || nvl2(cname8, ',' || cname8, null) columns from (select b.table_name, b.constraint_name, max(decode(position, 1, column_name, null)) cname1, max(decode(position, 2, column_name, null)) cname2, max(decode(position, 3, column_name, null)) cname3, max(decode(position, 4, column_name, null)) cname4, max(decode(position, 5, column_name, null)) cname5, max(decode(position, 6, column_name, null)) cname6, max(decode(position, 7, column_name, null)) cname7, max(decode(position, 8, column_name, null)) cname8, count(*) col_cnt from (select substr(table_name, 1, 30) table_name, substr(constraint_name, 1, 30) constraint_name, substr(column_name, 1, 30) column_name, position from user_cons_columns) a, user_constraints b where a.constraint_name = b.constraint_name and b.constraint_type = 'R' group by b.table_name, b.constraint_name) cons where col_cnt> ALL (select count(*) from user_ind_columns i where i.table_name = cons.table_name and i.column_name in (cname1, cname2, cname3, cname4, cname5, cname6, cname7, cname8) and i.column_position<= cons.col_cnt group by i.index_name)
选择性高的列(唯一值比例高的列)更适合建立索引。可以通过计算列唯一值与总行数比例来评估。
示例:
-- 评估索引列的选择性 SELECT COUNT(DISTINCT column_name) / COUNT(*) AS selectivity FROM table_name; -- 高选择性(接近1)表示该列适合建立索引 -- 低选择性(接近0)表示该列不适合单独建立索引 -- 示例:评估CUSTOMER表中EMAIL列的选择性 SELECT COUNT(DISTINCT EMAIL) / COUNT(*) AS email_selectivity FROM CUSTOMER;

未完待续…
Oracle数据库设计规范篇{六}——索引规范【下】(联合、无、失效索引及数量)
公众号:收获不止数据库
微信:ljbyxl1213
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/9091385/viewspace-3083545/ ,如需转载,请注明出处,否则将追究法律责任。