我有一张桌子,我希望在一张相当宽的桌子上每月可以获得700万张唱片。这些记录中的一小部分预计被标记为"问题"记录。
实现表格以有效方式查找这些记录的最佳方法是什么?
我是Oracle新手,但物化视图是有效选项吗?在Oracle中是否有这样的东西,比如索引视图,或者这可能真的是一回事吗?
大多数报告是按月进行的,因此按月分区似乎是一种选择,但问题是"记录可能在理论上持续数月。否则,报告收集主要是当月。您是否希望查询所有月份分区以查找任何问题记录与使用单个表相比会导致严重的性能问题?
您对从何处开始的一般想法将不胜感激。我意识到我需要阅读并且我会这样做,但我想首先考虑社区,以确保我读到正确的东西。
还有一个想法:主键是GUID varchar2(36)。在数量级上,您希望这相对于使用NUMBER数据类型PK有多大的性能影响?这令我担心,但这是我无法控制的。
答案 0 :(得分:2)
这取决于“标记”的含义,但对我来说听起来像是从简单的索引,基于函数的索引或索引的虚拟列中受益。
在所有情况下,您应该小心确保所有索引列对于不需要标记的行是NULL。这样,您的索引将只包含标记的行(Oracle不会 - 默认情况下 - 索引所有索引列值为NULL的B-Tree索引中的行)。
您的主键是VARCHAR2 GUID应该没有区别,至少在此问题的行中具体标记indexes will point to rows via Oracle internal ROWIDs。
索引支持分区,因此如果您的数据已经分区,则可以将索引设置为匹配。
简单列索引方法
如果您可以指示标记是如何工作的,或者列已经存在,那么我只需添加一个索引就像这样:
CREATE INDEX my_table_problems_idx ON my_table (problem_flag)
/
基于功能的索引方法
如果数据模型已修复/没有标志列,则可以创建基于函数的索引,假设您拥有目标表中所需的所有信息。例如:
CREATE INDEX my_table_problems_fnidx ON my_table (
CASE
WHEN amount > 100 THEN 'Y'
ELSE NULL
END
)
/
现在,如果在SELECT语句中使用相同的逻辑,则应该发现它使用索引来有效地匹配行。
SELECT *
FROM my_table
WHERE CASE
WHEN amount > 100 THEN 'Y'
ELSE NULL
END IS NOT NULL
/
虽然这有点笨拙,但它要求您在查询中使用与索引定义相同的逻辑。不是很好。您可以使用视图来屏蔽它,但您仍然至少在两个位置复制逻辑。
索引虚拟列
在我看来,如果你动态计算价值(从11g开始可用),这是最好的方法:
ALTER TABLE my_table
ADD virtual_problem_flag VARCHAR2(1) AS (
CASE
WHEN amount > 100 THEN 'Y'
ELSE NULL
END
)
/
CREATE INDEX my_table_problems_idx ON my_table (virtual_problem_flag)
/
现在您可以只查询虚拟列,就好像它是一个真正的列,即
SELECT *
FROM my_table
WHERE virtual_problem_flag = 'Y'
/
这将使用索引并将基于函数的逻辑放在一个地方。
答案 1 :(得分:0)
创建一个只包含问题行的pks的新表。