LightDB 从23.4开始支持 no_star_transformation hint。
在Oracle 中no_star_transformation hint 用于提示优化器不执行星型转换。LightDB 不支持星型转换,因此 no_star_transformation hint 总是会起效,下面先介绍下星型转换,然后介绍下hint的用法。
Oracle 星型转换
星型转换是一种优化器转换,它避免了对星型模式中事实表的全表扫描(星型模式将数据分为事实表和维度表)。
在事实表和维度表的连接中,星型转换可以避免对事实表的全表扫描。星型转换通过位图索引来获取事实表上需要的行(由维度表过滤),从而提高性能。
在某些情况下,查询在维度表的非关联列上有过滤条件。通过组合这些过滤条件可以显著减少数据库需要处理的来自事实表的数据集。
转换后查询按如下两阶段执行:
- 第一阶段是由事实表利用位图索引的位图信息 (或者由 B*树索引的 ROWID 转换得来的位图信息)进行位图操作,进而获得相应数据集;
- 第二阶段则将第一阶段获得的数据集与维度表进行关联,获取最终查询结果。
使用示例
初始化
CREATE TABLE times (
time_id NUMBER PRIMARY KEY,
calendar_quarter_desc VARCHAR2(20)
);
CREATE TABLE customers (
cust_id NUMBER PRIMARY KEY,
cust_city VARCHAR2(20),
cust_state_province VARCHAR2(20)
);
CREATE TABLE channels (
channel_id NUMBER PRIMARY KEY,
channel_class VARCHAR2(20),
channel_desc VARCHAR2(20)
);
CREATE TABLE sales (
time_id NUMBER REFERENCES times(time_id),
cust_id NUMBER REFERENCES customers(cust_id),
channel_id NUMBER REFERENCES channels(channel_id),
amount_sold NUMBER
);
-- oracle 中需要对事实表建立bitmap索引, LightDB 不支持bitmap 索引,不执行
--create bitmap index sales_i1 on sales(time_id);
--create bitmap index sales_i2 on sales(cust_id);
--create bitmap index sales_i3 on sales(channel_id);
执行SQL
lightdb@postgres=# EXPLAIN (COSTS false) SELECT/*+no_star_transformation*/ ch.channel_class, c.cust_city, t.calendar_quarter_desc,
SUM(s.amount_sold) sales_amount
FROM sales s, times t, customers c, channels ch
WHERE s.time_id = t.time_id
AND s.cust_id = c.cust_id
AND s.channel_id = ch.channel_id
AND c.cust_state_province = 'CA'
AND ch.channel_desc in ('Internet','Catalog')
AND t.calendar_quarter_desc IN ('1999-Q1','1999-Q2')
GROUP BY ch.channel_class, c.cust_city, t.calendar_quarter_desc;
LOG: lt_hint_plan:
used hint:
no_star_transformation
not used hint:
duplication hint:
error hint:
QUERY PLAN
----------------------------------------------------------------------------
---------------------------
GroupAggregate
Group Key: ch.channel_class, c.cust_city, t.calendar_quarter_desc
-> Sort
Sort Key: ch.channel_class, c.cust_city, t.calendar_quarter_desc
-> Nested Loop
-> Nested Loop
-> Hash Join
Hash Cond: (s.cust_id = c.cust_id)
-> Seq Scan on sales s @"lt#0"
-> Hash
-> Seq Scan on customers c @"lt#0"
Filter: ((cust_state_province)::text
= 'CA'::text)
-> Index Scan using times_pkey on times t @"lt#0"
Index Cond: (time_id = s.time_id)
Filter: ((calendar_quarter_desc)::text = ANY ('{1
999-Q1,1999-Q2}'::text[]))
-> Index Scan using channels_pkey on channels ch @"lt#0"
Index Cond: (channel_id = s.channel_id)
Filter: ((channel_desc)::text = ANY ('{Internet,Catalog
}'::text[]))
(18 rows)