我想索引此查询子句 - 请注意该文本是静态的。
SELECT * FROM tbl where flags LIKE '%current_step: complete%'
要重新迭代,current_step: complete
永远不会在查询中发生变化。我想构建一个有效预先计算此布尔值的索引,从而阻止全表扫描......
我宁愿不添加布尔列来存储预先计算的值,因为这需要在应用程序中更改代码....
答案 0 :(得分:3)
如果您不想更改查询,并且这不仅仅是一个问题,也不是更改数据维护(在这种情况下虚拟列和/或索引可以完成工作),您可以使用物化应用过滤器的视图,并让查询重写使用它而不是真实表。这可能是矫枉过正,但是可以选择。
模拟版本的原始计划:
explain plan for
SELECT * FROM tbl where flags LIKE '%current_step: complete%';
select * from table(dbms_xplan.display);
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 60 | 3 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| TBL | 2 | 60 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("FLAGS" IS NOT NULL AND "FLAGS" LIKE '%current_step:
complete%')
一个物化视图,它只保存您的查询感兴趣的记录(这是一个简单的示例,但您需要决定如何刷新并在需要时添加日志):
create materialized view mvw
enable query rewrite as
SELECT * FROM tbl where flags LIKE '%current_step: complete%';
现在您的查询点击了物化视图,感谢query rewrite:
explain plan for
SELECT * FROM tbl where flags LIKE '%current_step: complete%';
select * from table(dbms_xplan.display);
-------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 60 | 3 (0)| 00:00:01 |
| 1 | MAT_VIEW REWRITE ACCESS FULL| MVW | 2 | 60 | 3 (0)| 00:00:01 |
-------------------------------------------------------------------------------------
但是任何其他查询仍将使用原始表:
explain plan for
SELECT * FROM tbl where flags LIKE '%current_step: working%';
select * from table(dbms_xplan.display);
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 27 | 3 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| TBL | 1 | 27 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("FLAGS" LIKE '%current_step: success%' AND "FLAGS" IS NOT
NULL)
当然,如果允许修改查询,虚拟索引会更简单......
答案 1 :(得分:0)
您可能正在寻找全文搜索索引。
有几种方法可以实现这个:
答案 2 :(得分:0)
我宁愿不添加布尔列来存储预先计算的值,因为这需要在应用程序中更改代码
我可以建议两种方式:
<强> 1 强>
如果您使用的是11g及以上,当值为VIRTUAL COLUMN
时,您可以将complete
始终生成为1,然后您需要执行此操作:
select * from table where virtual_column = 1
为了提高效果,你可以有一个索引,相当于function-based index
。
<强> 2 强>
更新:也许,我应该更清楚我的第二点:source
在某些情况下,Oracle会使用index
来解析'%text%'
模式的类似内容。如果可以在不必返回到表(rowid lookup)的情况下解析查询,则可以选择索引。示例:
select distinct first_nm from person where first_nm like '%EV%';
在上述情况下,Oracle会执行 index fast full scan
- 对较小索引的完整扫描。