sql查询需要花费很多时间

时间:2011-07-11 09:26:15

标签: sql oracle parallel-processing hint

我正在运行以下查询:

SELECT * 
  FROM dblappc.credit_history 
 WHERE crd_effective_date > TO_DATE('20100801','YYYYMMDD') 
   AND o_crd_score > 650 
   AND crd_expiration_date IS NULL
  • 上表没有索引
  • crd_expiration_date是主键的一部分

如何加快查询速度?
我可以在这里使用并行提示,以便至少一次提供500行吗?

下面是表格结构:

CREATE TABLE DFQAPP13.CREDIT_HISTORY
(
  BAN                  NUMBER(9) CONSTRAINT CRHST_BAN_NN NOT NULL,
  CRD_SEQ_NO           NUMBER(9) CONSTRAINT CRDHST_CRD_SEQ_NO_NN NOT NULL,
  SYS_CREATION_DATE    DATE                     NOT NULL,
  SYS_UPDATE_DATE      DATE,
  OPERATOR_ID          NUMBER(9),
  APPLICATION_ID       CHAR(6 BYTE),
  DL_SERVICE_CODE      CHAR(5 BYTE),
  DL_UPDATE_STAMP      NUMBER(4),
  CRD_EFFECTIVE_DATE   DATE CONSTRAINT CRDHST_CRD_EFFECTIVE_DATE_NN NOT NULL,
  CRD_EXPIRATION_DATE  DATE,
  CRD_VET_TYPE         CHAR(4 BYTE),
  O_CRD_APPLIC_NUM     NUMBER(9),
  O_CRD_DECISION       CHAR(2 BYTE),
  O_CRD_SCORE          NUMBER(7),
  O_CRD_POLICY_RULE1   VARCHAR2(40 BYTE),
  O_CRD_POLICY_RULE2   VARCHAR2(40 BYTE),
  O_CRD_POLICY_RULE3   VARCHAR2(40 BYTE),
  O_CRD_POLICY_RULE4   VARCHAR2(40 BYTE),
  O_CRD_POLICY_RULE5   VARCHAR2(40 BYTE),
  O_CRD_POLICY_RULE6   VARCHAR2(40 BYTE),
  CRD_CLASS            CHAR(1 BYTE),
  CRD_CLASS_CHG_TYPE   CHAR(1 BYTE),
  CRD_CHG_RSN_TEXT     CHAR(100 BYTE),
  I_CRD_REQ_CTN_QTY    NUMBER(7),
  CRD_APR_CTN_QTY      NUMBER(7),
  I_CRD_BANK_BRANCH    VARCHAR2(100 BYTE),
  I_CRD_TACT_BANK_CD   CHAR(1 BYTE),
  I_CRD_BANK_DATE      DATE,
  I_ESAT_CUST_IND      CHAR(1 BYTE),
  O_DUNS_RET_CODE1     CHAR(4 BYTE),
  O_DUNS_RET_CODE2     CHAR(4 BYTE),
  O_DUNS_RET_NUM       VARCHAR2(18 BYTE),
  O_DUNS_NUM           NUMBER(9),
  O_DUNS_FIN_STRENGTH  CHAR(3 BYTE),
  O_DUNS_COMP_COND     CHAR(1 BYTE),
  O_DUNS_PAYM_SCORE    NUMBER(4),
  O_DUNS_CCJ1_EIRE     NUMBER(6),
  O_DUNS_CCJ2_EIRE     NUMBER(6),
  O_DUNS_CCJ3_EIRE     NUMBER(6),
  O_DUNS_CCJ4_EIRE     NUMBER(6),
  O_DUNS_CCJ5_EIRE     NUMBER(6),
  O_DUNS_CCJ1_UK       NUMBER(4),
  O_DUNS_CCJ2_UK       NUMBER(4),
  O_DUNS_CCJ3_UK       NUMBER(4),
  O_DUNS_CCJ4_UK       NUMBER(4),
  O_DUNS_CCJ5_UK       NUMBER(4),
  I_PHONE_TYPE         CHAR(3 BYTE),
  I_PAID_ENHANCE_NUM   NUMBER(1),
  I_CHURN_CUST_IND     CHAR(1 BYTE),
  I_EX_DIRECTORY_IND   CHAR(1 BYTE),
  I_ITEMISED_BIL_IND   CHAR(1 BYTE),
  CONV_RUN_NO          NUMBER(3)
)

3 个答案:

答案 0 :(得分:2)

在不知道表格大小,现有索引,执行计划和其他细节的情况下,很难提供任何建议。

由于查询在两个范围内搜索,因此仅使用索引获取所有结果并不容易。

但我先尝试这两个选项:

  • crd_effective_date上的简单索引及(crd_expiration_date, o_crd_score)

    上的复合
  • o_crd_score上的简单索引和(crd_expiration_date, crd_effective_date)上的复合

您可以使用:EXPLAIN PLAN

检查查询的执行计划(现在,没有索引,添加后)

答案 1 :(得分:0)

有一个具体问题和一些一般性改进。

首先,null值未编入索引,因此Oracle最有可能选择使用索引构建在主键上方的查询的完整索引扫描或索引跳过扫描变体。 如果您确实需要将crd_expiration_date包含在主键中,请仅在o_crd_scorecrd_effective_date字段中为此查询创建另一个索引。

create index X_CREDIT_HISTORY_DATE_SCORE 
  on CREDIT_HISTORY (o_crd_score, crd_effective_date)

如果之后Oracle不会使用新索引强制它在查询文本中:

select /*+ index(hist_data X_CREDIT_HISTORY_DATE_SCORE) */ 
  * 
from 
  dblappc.credit_history hist_data
where 
  crd_effective_date>to_date('20100801','YYYYMMDD') 
  and 
  o_crd_score >650 
  and 
  crd_expiration_date is null

一般问题很常见,在以前的答案中提到过:

  1. 仅选择您真正需要的特定字段;
  2. 避免在主键中使用空值;
  3. 首选代理主键。
  4. 更新

    Oooops ...... 我之前在阅读问题时错过了“上表没有索引”的短语。

    因此只有一个建议:只需创建一个索引。

答案 2 :(得分:-2)

你可以通过

加快速度
  • 选择要减少结果权重的特定项目。
  • 在WHERE子句中首先使用o_crd_score >650crd_expiration_date is null排在第二位 最后的crd_effective_date>to_date('20100801','YYYYMMDD')

所以查询就像。

SELECT a,b,d... 
FROM dblappc.credit_history
WHERE 
  o_crd_score >650 and 
  crd_expiration_date is null
  crd_effective_date>to_date('20100801','YYYYMMDD') and 

我在这里做的是将记录短路到最小,以便将日期检查应用于过滤掉的记录。

您也可以通过在表格上应用INDEX来加快速度。