6

我有一个查询,我正在搜索一个字符串:

SELECT county FROM city WHERE UPPER(name) = 'SAN FRANCISCO';

现在,这工作正常,但它不能很好地扩展,我需要优化它。我找到了一个类似于创建生成视图的选项,或者类似的东西,但我希望使用索引有一个更简单的解决方案。

我们正在使用 DB2,我真的想在 index 中使用表达式,但是这个选项似乎只在 z/OS 上可用,但是我们正在运行 Linux。我还是尝试了表达式索引:

CREATE INDEX city_upper_name_idx
ON city UPPER(name) ALLOW REVERSE SCANS;

但当然,它会在 UPPER(name) 上窒息。

有没有另一种方法可以以这种方式创建索引或类似的东西,这样我就不必重组现有查询以使用新生成的视图,或更改现有列或任何其他此类侵入性更改?

编辑:我愿意听取其他数据库的解决方案......它可能会延续到 DB2......

4

6 回答 6

7

您可以添加一个索引列,其中包含城市名称的数字哈希键。(允许重复)。

然后你可以做一个多子句 where :

hash = [compute hash key for 'SAN FRANCISCO']

SELECT county 
FROM city 
WHERE cityHash = hash 
  AND UPPER(name) = 'SAN FRANCISCO' ;

或者,查看您的数据库手册并查看创建表索引的选项。可能会有一些帮助。

于 2008-08-15T23:28:22.687 回答
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 对象。

有关详细信息,请参见此处

于 2009-01-07T06:22:22.897 回答
2

我不知道这在 DB2 中是否可行,但我会告诉您如何在 SQL Server 中执行此操作。我认为MSSQL 这样做的方式是 ANSI 标准,尽管具体的排序规则字符串可能不同。无论如何,如果您可以在不破坏应用程序的其余部分的情况下做到这一点——是否还有其他地方的“名称”列需要区分大小写?-- 尝试通过更改排序规则使整列不区分大小写,然后对该列进行索引。

ALTER TABLE city ALTER COLUMN name nvarchar(200) 
    COLLATE SQL_Latin1_General_CP1_CI_AS

...其中“nvarchar(200)”代表您当前的列数据类型。排序规则字符串的“CI”部分在 MSSQL 中将其标记为不区分大小写。

解释一下......我的理解是索引将按照索引列的排序规则存储值。使列的排序规则不区分大小写将使索引存储 'San Francisco'、'SAN FRANCISCO' 和 'san francisco' 放在一起。然后您应该只需要从查询中删除“UPPER()”,DB2 应该知道它可以使用您的索引。

同样,这完全基于我对 SQL Server 的了解,加上几分钟查看 SQL-92 规范;它可能适用于 DB2,也可能不适用于 DB2。

于 2008-08-19T16:59:22.657 回答
1

PostgreSQL 还支持对函数的结果进行索引:

CREATE INDEX mytable_lower_col1_idx ON mytable (lower(col1));

我能想到的唯一其他选择是通过创建另一列来保存大写版本(由触发器更新)并对其进行索引,从而对您的数据进行一些反规范化。布莱赫!

于 2008-08-16T12:40:25.117 回答
1

DB2 在整理方面并不强。而且它没有基于函数的索引。

如果您可以接受散列必须在您的应用程序中发生(因为据我所知,DB2 没有 SHA 或 MD5 函数),Niek Sanders 的建议会奏效。

但是,如果我是你,我会使用CREATE TABLE AS创建一个物化视图(MQT == Materialized Query Table,用 db2 的说法) ,添加一个具有预先计算的名称大写变体的列。注意:您可以向 DB2 中的物化视图添加索引。

于 2008-09-03T23:04:09.993 回答
1

Oracle 支持基于函数的索引。他们的典型例子:

 create index emp_upper_idx on emp(upper(ename));  
于 2008-08-16T02:13:32.883 回答