0

我在 Oracle 11g 上,我们有以下 3 个核心表:

Customer - CUSTOMERID|DOB
CustomerName - CUSTOMERNAMEID|CustomerID|FNAME|LNAME
Address - ADDRESSID|CUSTOMERID|STREET|CITY|STATE|POSTALCODE

我在每个表上都有大约 6000 万行,数据是美国和加拿大人口的混合体。

我有一个调用 Web 服务的前端应用程序,他们执行姓氏和部分 zip 搜索。所以我的查询基本上有

where CUSTOMERNAME.LNAME = ? and ADDRESS.POSTALCODE LIKE '?%'

它们通常提供 zip 的前 3 位数字。

地址表在所有街道/城市/州/邮编上都有一个索引,在州和邮编上还有一个索引。

我确实尝试为 zip 添加专门的索引,并强制 oracle 在我的查询中使用该索引,但这没有任何区别。

返回大约 100 行(我的分页一次只返回 100 行)大约需要 30 秒,这并不理想。我能做些什么来让这变得更好?

4

1 回答 1

0

问题是您应用的过滤器不是很有选择性,它们适用于不同的表。这对于老式的 btree 索引是不利的。如果内容非常静态,您可以尝试位图索引。更准确地说,基于函数的位图连接索引对姓氏的前三个字母和邮政编码列的位图连接索引。这假设很少有姓氏以特定字母开头的人居住在具有特定邮政编码的地区。

CREATE BITMAP INDEX ix_customer_custname ON customer(SUBSTR(cn.lname,1,3))
FROM customer c, customername cn
WHERE c.customerid = cn.customerid;

CREATE BITMAP INDEX ix_customer_postalcode ON customer(SUBSTR(a.postalcode,1,3))
FROM customer c, address a
WHERE c.customerid = a.customerid;

如果您成功了,您应该会看到两个位图索引变为 AND 连接。执行时间应该下降到几秒钟。它不会像 btree 索引那样快。

评论:

  • 您可能需要考虑一下是否创建一个或两个索引更有效,以及该函数是否有用。

  • 如果您决定基于函数执行此操作,则应在查询的 where 子句中包含完全相同的函数调用。否则将不会使用索引。

  • DML 操作会慢很多。这仅对具有静态数据的表有用。请注意,DML 操作将阻止整行“范围”。并发 DML 操作会遇到问题。

  • 响应时间可能仍然是秒,而不是像 BTREE 索引那样立即。

  • AFAIK 这仅适用于企业版。该语法未经测试,因为我目前没有可用的企业数据库。

  • 如果这仍然不够快,您可以使用 customerid、姓氏和邮政编码创建一个物化视图,但上面有一个 btree 索引。但这也有点贵。

于 2017-10-17T22:00:23.340 回答