我使用的一个表有一个char(19)列,我们称之为P。由于某些情况,我需要检查是否在P中找到一个10个字符的变量(在P中字符串的末尾)。因此我这样做:其中P像CONCAT(' %',variableName)。
因此性能很差。一个可能的解决方案是现在引入一个自动更新/计算的列,让我们用char(10)称之为P10。然后我可以使用where P10 like variableName,这更好。(特别是当涉及到索引时)。
现在的问题是什么是性能方面更好的方法(我没有找到任何信息)?-Alter TABLE MyTable add column P10 char(10)GENERATED ALWAYS AS substr(P,9,10)-或者触发事件,用来自P的子字符串填充P10
2条答案
按热度按时间w3nuxt5m1#
Generated ALWAYS列只是实现此目的的一种方法
在表
MyTable
上添加和索引派生/生成的CHAR(10)
列P10
并不是加速搜索CHAR(19)
列P
的最后10个字符的查询的唯一方法,但是如果您最终选择这种方法,将列P10
定义为GENERATED ALWAYS
比通过触发器填充P10
有一些优点。除了相对简单和由DBMS更严格地维护外,GENERATED ALWAYS
列还提供了重要的上下文,即使语句没有引用生成的列,但以正确的方式引用了基列,查询优化器也可以利用这些上下文。在问题中描述的场景中,添加列
P10 CHAR(10) GENERATED ALWAYS AS (SUBSTR(P, 10, 10))
,然后添加CREATE INDEX ixmytblp10 ON MyTable (P10)
,至少会使以下语句受益:字符串
第一条语句直接引用
P10
,并将如预期的那样从索引中受益。第二条语句根本没有提到索引列,但查询优化器应该注意到该语句在P
上有一个表达式,该表达式完全匹配GENERATED ALWAYS
列P10
的定义,然后利用P10
上的索引。调优SQL时必须使用查询解释实用程序
查询解释实用程序(如
db2expln
或db2exfmt
)将向您显示给定SQL语句的详细访问计划,并显示该语句是否将使用您创建的索引。例如,explain实用程序不太可能为...WHERE MyTable.P LIKE '%' || some10charactervalue
生成理想的访问计划,因为LIKE模式开头的%
前缀实际上是一个 * ends-with* 搜索,通常扫描整个索引(如果不是整个表)。可变长度注意事项
如果
P
的给定值包含少于19个字符,您可能需要考虑在GENERATED ALWAYS
列定义和SQL查询中用更灵活的表达式(如RIGHT(RTRIM(P), 10)
)替换SUBSTR(P, 10, 10)
,以便它们可以更可靠地从P
列中获取最后10个非空格字符,无论它包含什么。基于表达式的索引是另一种方法
这个问题的另一个答案正确地指出,如果您在列
P
上创建基于表达式的索引,并确保应用程序在查询中使用该表达式,则不需要生成列。如果P
的每个非NULL值都恰好包含19个字符,则CREATE INDEX ixmytblp10 ON MyTable (SUBSTR(P, 10, 10))
应该可以工作,否则使用更灵活的值,如CREATE INDEX ixmytblp10 ON MyTable (RIGHT(RTRIM(P), 10))
zujrkrfu2#
如果你确定列
P
总是19个字符的长度,并且搜索值总是10个字符的长度,你可以索引搜索表达式并使用它进行搜索(完全按照索引的方式输入)。例如:字符串
请参见db<>fiddle上的运行示例。
请注意,
substr(p, 10, 10)
的键入方式与SELECT中的字母完全相同。或者,如果你想搜索字符串的最后一个字符,一般的解决方案是索引反转的值,然后使用反转模式进行搜索。这样
%
将位于搜索模式的末尾,引擎将自然使用索引。