我有一个查询,我在搜索字符串:
SELECT county FROM city WHERE UPPER(name) = 'SAN FRANCISCO';
现在,这种方法很好,但它不能很好地扩展,我需要优化它。我有found an option沿着创建生成视图的方式,或类似的东西,但我希望使用索引的更简单的解决方案。
我们正在使用DB2,我真的想使用expression in an index,但是这个选项似乎只能在z / OS上使用,但我们运行的是Linux。我还是尝试了表达式索引:
CREATE INDEX city_upper_name_idx
ON city UPPER(name) ALLOW REVERSE SCANS;
但当然,它在UPPER(名字)上窒息。
我是否有另一种方法可以以这种方式创建索引或类似内容,这样我就不必重新构建现有查询以使用新生成的视图,或更改现有列,或任何其他此类侵入式更改?
编辑:我愿意听取其他数据库的解决方案......它可能会延续到DB2 ......
答案 0 :(得分:7)
您可以添加一个包含城市名称的数字哈希键的索引列。 (允许重复)。
然后你可以做一个多子句:
hash = [compute hash key for 'SAN FRANCISCO']
SELECT county
FROM city
WHERE cityHash = hash
AND UPPER(name) = 'SAN FRANCISCO' ;
或者,浏览db手册并查看创建表索引的选项。可能会有所帮助。
答案 1 :(得分:5)
简短回答,不。
答案很长,是的,如果你在大型机上运行,但你不是,所以你必须使用其他技巧。
DB2(从DB2 / LUW v8开始)现在已生成列,因此您可以:
CREATE TABLE tbl (
lname VARCHAR(20),
fname VARCHAR(20),
ulname VARCHAR(20) GENERATED ALWAYS AS UPPER(lname)
);
然后在ulname上创建索引。我不确定你会比这更简单。
在此之前,您曾经必须使用插入和更新触发器的组合来确保ulname列保持同步,这是一个维护的噩梦。此外,既然此功能是核心DBMS的一部分,它已经过高度优化(它比基于触发器的解决方案快得多),并且不会妨碍真正的用户触发器,因此无需维护额外的DB对象。 / p>
有关详细信息,请参阅here。
答案 2 :(得分:1)
Oracle支持基于函数的索引。他们的典型例子:
create index emp_upper_idx on emp(upper(ename));
答案 3 :(得分:1)
PostgreSQL还支持索引函数的结果:
CREATE INDEX mytable_lower_col1_idx ON mytable (lower(col1));
我能想到的唯一另一个选择是通过创建另一个列来保存大写版本(由触发器更新)并对其进行索引来对数据进行一些标准化。布莱什!
答案 4 :(得分:1)
我不知道这是否适用于DB2,但我会告诉你我是如何在SQL Server中这样做的。我认为 MSSQL这样做的方式是ANSI标准,尽管特定的排序字符串可能不同。无论如何,如果你可以做到这一点而不会破坏你的应用程序的其余部分 - 还有其他地方,“名称”列需要区分大小写吗? - 尝试通过更改排序规则使整个列不区分大小写,然后将列索引。
ALTER TABLE city ALTER COLUMN name nvarchar(200)
COLLATE SQL_Latin1_General_CP1_CI_AS
...其中“nvarchar(200)”代表您当前的列数据类型。排序字符串的“CI”部分标记为在MSSQL中不区分大小写。
要解释......我的理解是索引将按索引列的排序规则的顺序存储值。使列的排序规则不区分大小写将使索引存储“旧金山”,“旧金山”和“旧金山”全部合并在一起。然后你应该从查询中删除“UPPER()”,DB2应该知道它可以使用你的索引。
同样,这完全基于我对SQL Server的了解,加上几分钟的SQL-92规范;它可能适用于DB2也可能不适用。
答案 5 :(得分:1)
DB2在整理方面不强。它没有基于功能的索引。
Niek Sanders的建议可行,如果你能接受哈希必须在你的应用程序中发生(因为据我所知,DB2没有SHA或MD5函数)。
但是,如果我是你,我将使用CREATE TABLE AS创建一个物化视图(MQT ==物化查询表,在db2用语中),添加一个列,其中包含预先计算的大写变体名称。注意:您可以在DB2中为实现视图添加索引。