问题描述
嗨,
我有非常大的表,表不断增长。搜索由ID列执行,该列是PK的一部分。
同时,大多数select查询都在寻找相对较新的记录 (即几个月)。为了避免一直进行全索引扫描,我可以尝试分两步执行查询-首先,我使用其他谓词搜索时间范围,即
只有当找不到记录时,我才会对所有日期执行查询-
将被限制为只有一个查询的时间99%。很好,特别是如果我们在 (CREATED_TS,ID) 上添加索引。但是当我需要搜索ID值列表时,即使用
是否可以使用内置的Oracle功能来实现相同的逻辑?例如,我正在考虑通过CREATED_TS范围对表进行分区。如果可以以某种方式让Oracle知道它应该在最近的分区中开始搜索,则可以解决挑战。但是我不知道有序分区扫描的优化提示。
我不认为这是不寻常的情况,所以期待一些已经存在的解决方案从Oracle。
谢谢,
亚历山大
我有非常大的表,表不断增长。搜索由ID列执行,该列是PK的一部分。
create table TEST ( ID varchar2(20) primary key, VALUE varchar2(20), CREATED_TS timestamp default := systimestamp );
同时,大多数select查询都在寻找相对较新的记录 (即几个月)。为了避免一直进行全索引扫描,我可以尝试分两步执行查询-首先,我使用其他谓词搜索时间范围,即
select * from TEST where ID='xyz' and CREATED_TS > systimestamp-100
只有当找不到记录时,我才会对所有日期执行查询-
select * from TEST where ID='xyz'
将被限制为只有一个查询的时间99%。很好,特别是如果我们在 (CREATED_TS,ID) 上添加索引。但是当我需要搜索ID值列表时,即使用
"ID in ('val1', 'val2', 'val3'...)"语法。在这种情况下,我需要通过第一步找不到的值来缩小第二步的列表。这很不方便。是否可以使用内置的Oracle功能来实现相同的逻辑?例如,我正在考虑通过CREATED_TS范围对表进行分区。如果可以以某种方式让Oracle知道它应该在最近的分区中开始搜索,则可以解决挑战。但是我不知道有序分区扫描的优化提示。
我不认为这是不寻常的情况,所以期待一些已经存在的解决方案从Oracle。
谢谢,
亚历山大
专家解答
关于
"select * from TEST where ID='xyz' and CREATED_TS > systimestamp-100
an only if record is not found I will execute query for all dates -
select * from TEST where ID='xyz'
"
如果您在ID上有索引,CREATED_TS,那么您将不需要第一个查询-是否有ID的数据。然后可以将相同的逻辑应用于多个ID。优化器应该迭代地处理它们以利用该索引,或者最坏的情况是,您可以将它们表述为UNION ALL。
但是,如果您的测试用例是对更一般情况的简化,即,用户给出了完全临时的搜索条件,并且您想 * 首先 * 搜索最近的数据,那么在这种情况下,在适当的日期/时间戳列上进行分区是一种有效的策略,因为仅对相关分区进行全面扫描就可以提高查询性能。分区也有助于满足以下要求: “首先检查最近,否则返回更远”,因为您可以将查询表述为:
查询1: 其中 [标准] 和ts >= [起点]
查询2: 其中 [标准] 和ts <[起点]
这避免了重复扫描最近的分区。
无论哪种情况,都可以使用良好的应用程序工具来识别随时间推移的 “流行” 查询,并且可以使用专门的索引来处理最常见的查询,以提供良好的用户体验。
显然,这里还有其他因素可能会发挥作用。例如,如果您有一个Exadata系统,那么存储索引可能会减轻分区等的需求。
希望这有所帮助。
"select * from TEST where ID='xyz' and CREATED_TS > systimestamp-100
an only if record is not found I will execute query for all dates -
select * from TEST where ID='xyz'
"
如果您在ID上有索引,CREATED_TS,那么您将不需要第一个查询-是否有ID的数据。然后可以将相同的逻辑应用于多个ID。优化器应该迭代地处理它们以利用该索引,或者最坏的情况是,您可以将它们表述为UNION ALL。
但是,如果您的测试用例是对更一般情况的简化,即,用户给出了完全临时的搜索条件,并且您想 * 首先 * 搜索最近的数据,那么在这种情况下,在适当的日期/时间戳列上进行分区是一种有效的策略,因为仅对相关分区进行全面扫描就可以提高查询性能。分区也有助于满足以下要求: “首先检查最近,否则返回更远”,因为您可以将查询表述为:
查询1: 其中 [标准] 和ts >= [起点]
查询2: 其中 [标准] 和ts <[起点]
这避免了重复扫描最近的分区。
无论哪种情况,都可以使用良好的应用程序工具来识别随时间推移的 “流行” 查询,并且可以使用专门的索引来处理最常见的查询,以提供良好的用户体验。
显然,这里还有其他因素可能会发挥作用。例如,如果您有一个Exadata系统,那么存储索引可能会减轻分区等的需求。
希望这有所帮助。
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




