最好的方法来识别少数记录,预计将有一个标志设置为TRUE



我有一个表,我希望在一个相当宽的表上每月获得700万条记录。这些记录中的一小部分将被标记为"问题"记录。

什么是实现表的最佳方式,以有效的方式定位这些记录?

我是新的Oracle,但物化视图是一个有效的选项吗?在Oracle中有索引视图之类的东西吗?或者这可能真的是一样的东西吗?

大多数报告都是按月进行的,因此按月划分似乎是一种选择,但理论上一个"问题"记录可能会持续几个月。否则,报告应该主要是当月的。与使用单个表相比,您是否期望跨所有月份分区查询以定位任何问题记录会导致严重的性能问题?

如果你能告诉我从哪里开始,我将不胜感激。我意识到我需要阅读,我会这样做,但我想先得到社区的想法,以确保我读了正确的东西。

再考虑一下:主键是GUID varchar2(36)。在数量级上,与使用NUMBER数据类型PK相比,您认为这会对性能造成多大的影响?这让我担心,但我无法控制。

这取决于您对"标记"的含义,但在我看来,您将受益于简单索引,基于函数的索引或索引虚拟列。

  • 在任何情况下,您都应该小心确保对于不需要标记的行,所有索引列都为NULL。这样,你的索引将只包含被标记的行(默认情况下,Oracle不会在B-Tree索引中索引所有索引列值为NULL的行)。

  • 你的主键是一个VARCHAR2 GUID应该没有区别,至少在这个问题中关于行的特定标记,索引将通过Oracle内部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'
/

这将使用索引,并将基于函数的逻辑放在一个地方。

创建一个只包含问题行的pks的新表

相关内容

最新更新