Ива*_*ный 7 oracle partitioning
通常,如果您有一个经常查询表的列,则应该在其上粘贴索引。但是,如果事先知道所有可能的值,是否也值得按此列对表进行分区?假设您有一个表,AUDIT
其中的TenantId
列只能包含值:1, 2。
所有 SELECT
语句都有一个WHERE
带TenantId
参数的子句。
那么,通过 TenantId 对该表进行分区是否有益?如果是这样,您还会在TenantId
列上创建索引吗?
partition by list (TENANTID)
(
partition TENANT1 values (1),
partition TENANT2 values (2)
)
Run Code Online (Sandbox Code Playgroud)
我做了一个小实验:插入 1M 随机生成的 TenantId 记录,从而创建:
以下是语句的查询计划:
SELECT * FROM table1 WHERE TENANTID=2
Run Code Online (Sandbox Code Playgroud)
普通表(无索引,无分区)
位图索引:
分区:
顺便说一句,如果我同时拥有索引和分区,查询计划使用分区而不是索引,因此该计划看起来与上面显示的第二个完全相同。
显然分区获胜,但是呢? 显然,执行计划中的成本列并不是判断 SQL 语句响应时间的真实成本的可靠方法。
那么,什么是最好的方法呢?如何选择一个?
我的观点是,以所呈现的方式对该表进行分区可能是有用的。
如果进行完整扫描,您的查询将快两倍(在分区几乎相等的情况下)。
如果您的查询具有另一种过滤器/条件并使用索引,则分区没有用,因为索引的级别几乎不受值数量加倍的影响。
更新:对于您所做的测试(SELECT * FROM table1 WHERE TENANTID=2
),可以肯定分区是最好的。位图解决方案需要扫描索引,然后扫描包含行的所有表块tenantid=2
(它知道行是什么)。但是分区会导致只扫描tenantid=2的表分区。它们在物理上是分开的tenantid=1
。
因此,两次扫描(索引扫描+表扫描)与一次表扫描(可能更小)。