3

我的问题涉及 Oracle 11gr2 和 SQL 查询中索引的使用。请帮助我解决以下问题,我无法在此查询中使用索引:

SELECT ListingManagerID,
       FirstName,
       LastName,
       PrimaryPhone,
       AlternatePhone,
       Email,
       UserName,
       Password,
       RecallGuid,
       CustomerSince,
       PWChangeRequired,
       PWExpireDate,
       CallingHours,
       CreateDate,
       CreateIPAddress,
       LastLogin,
       AutoRenewFlag,
       LastUpdated,
       UpdatedBy,
       AutoRenewRemovedDate,
       AutoRenewDate,
       isSupplier,
       PrefferedLanguage,
       AboutMe,
       PictureFilePath,
       IsProfilePictureDisplay,
       LocaleID,
       Address1,
       Address2,
       CityID,
       CountryID,
       StateProvinceID,
       PostalCode,
       RegistrationSource,
       PPCTypeID,
       GhostUser,
       ProfileId,
       TimezoneID,
       OCA
FROM ListingManager
WHERE trim(lower(LISTINGMANAGERID)) = 'e.kkagacoe4aaae7rnr9lua5'
  1. 创建索引

SQL> CREATE INDEX IDX_LISTINGMANAGER_ID ON listingmanager (LOWER(listingmanagerid));

已创建索引。

  1. 收集统计数据

SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS('INTERSHOP', 'LISTINGMANAGER' , CASCADE=>TRUE);

PL/SQL 过程成功完成。

索引是在 上创建的Listingmanager Column,但执行计划仍然显示全表扫描。我不知道为什么仍然会发生全表扫描。

ListingManagerID 是表的主键,我可以修改主键创建的索引吗?

PLAN_TABLE_OUTPUT
--------------------------------------------------
| Id | Operation        | Name           | Rows | Bytes | Cost (%CPU)|    
--------------------------------------------------
| 0  | SELECT STATEMENT |                | 2013 | 487K| 1784 (1)|    
|* 1 | TABLE ACCESS FULL| LISTINGMANAGER | 2013 | 487K| 1784 (1)|

谓词信息(由操作 id 标识):

1 - filter(TRIM(LOWER("LISTINGMANAGERID"))='e.kkagacoe4aaae7rnr9lua5' )

谢谢

4

2 回答 2

5

Oracle 的函数索引非常敏感。您必须几乎完全使用您在查询中创建索引的内容。我不是 100% 确定,但它甚至可以扩展到空格和括号。在任何情况下,您的索引都没有被修剪,因此它不会用于修剪的谓词。

修剪和小写您的常量/参数而不是列(和/或存储修剪的、降低的副本),因此您根本不必使用基于函数的索引。如果在列上有一个函数,那么使用索引就会变得非常困难。

于 2013-05-24T09:22:56.603 回答
3

而不是您创建的索引,您需要创建这个:

CREATE INDEX IDX_LISTINGMANAGER_ID ON listingmanager (trim(LOWER(listingmanagerid)));

情况是功能索引应该与WHERE子句中的条件完全相同。

你也可以使用这个技巧来使你的索引工作:

SELECT 
  <fields>
FROM ListingManager
WHERE lower(LISTINGMANAGERID) like '%e.kkagacoe4aaae7rnr9lua5%'
AND trim(lower(LISTINGMANAGERID)) = 'e.kkagacoe4aaae7rnr9lua5'

但它被它的耳朵拉着。您还应该注意,有时优化器认为FULL TABLE SCAN检索数据比使用索引更有效,但我认为不是您的情况(要让优化器使用索引,您应该使用提示)。

例如,您使用提示的查询:

SELECT /*+ INDEX (ListingManager IDX_LISTINGMANAGER_ID)*/
       ListingManagerID,
       FirstName,
       LastName,
       PrimaryPhone,
       AlternatePhone,
       Email,
       UserName,
       Password,
       RecallGuid,
       CustomerSince,
       PWChangeRequired,
       PWExpireDate,
       CallingHours,
       CreateDate,
       CreateIPAddress,
       LastLogin,
       AutoRenewFlag,
       LastUpdated,
       UpdatedBy,
       AutoRenewRemovedDate,
       AutoRenewDate,
       isSupplier,
       PrefferedLanguage,
       AboutMe,
       PictureFilePath,
       IsProfilePictureDisplay,
       LocaleID,
       Address1,
       Address2,
       CityID,
       CountryID,
       StateProvinceID,
       PostalCode,
       RegistrationSource,
       PPCTypeID,
       GhostUser,
       ProfileId,
       TimezoneID,
       OCA
FROM ListingManager
WHERE trim(lower(LISTINGMANAGERID)) = 'e.kkagacoe4aaae7rnr9lua5'
于 2013-05-24T09:46:36.833 回答