简体   繁体   English

sql 查询需要很多时间

[英]sql query takes a lot of time

I am running the following query:我正在运行以下查询:

SELECT * 
  FROM dblappc.credit_history 
 WHERE crd_effective_date > TO_DATE('20100801','YYYYMMDD') 
   AND o_crd_score > 650 
   AND crd_expiration_date IS NULL
  • Above table has no indexes上表没有索引
  • crd_expiration_date is part of the primary key crd_expiration_date是主键的一部分

How can I speed up the query?如何加快查询速度?
Could I use parallel hint here so that to give 500 rows at a time at least?我可以在这里使用并行提示,以便一次至少提供 500 行吗?

Below is the table structure:下面是表结构:

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)
)

Without knowing the size of the table, the existing indexes, the execution plan and other details, it's hard to give any advice.在不知道表的大小、现有索引、执行计划和其他细节的情况下,很难给出任何建议。

Since the query is searching in two ranges, it's not easy to get all results using only indexes.由于查询在两个范围内进行搜索,因此仅使用索引来获取所有结果并不容易。

But I would try first these 2 options:但我会先尝试这两个选项:

  • Simple index on crd_effective_date and compound on (crd_expiration_date, o_crd_score) or crd_effective_date上的简单索引和(crd_expiration_date, o_crd_score)上的复合或

  • Simple index on o_crd_score and compound on (crd_expiration_date, crd_effective_date) o_crd_score上的简单索引和(crd_expiration_date, crd_effective_date)上的复合

You can check the execution plan of a query (now, without indexes and after adding them), using:EXPLAIN PLAN您可以使用以下命令检查查询的执行计划(现在,没有索引和添加它们之后):EXPLAIN PLAN

There are one specific issue and some general improvements.有一个具体问题和一些一般性改进。

Firstly, null values not indexed, therefore Oracle most probably choose to full index scan or index skip scan variants for your query with index build above primary key.首先, null值未编入索引,因此 Oracle 最有可能为您的查询选择全索引扫描或索引跳过扫描变体,索引构建高于主键。 If you really need to include crd_expiration_date into primary key, create another index for this query on o_crd_score and crd_effective_date fields only.如果您确实需要将crd_expiration_date包含到主键中,请仅在o_crd_scorecrd_effective_date字段上为此查询创建另一个索引。

create index X_CREDIT_HISTORY_DATE_SCORE 
  on CREDIT_HISTORY (o_crd_score, crd_effective_date)

If after that Oracle won't use new index force it in query text:如果之后 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

General issues are common and mentioned in previous answers:一般问题很常见,并在之前的答案中提到:

  1. Select only specific fields, which you really need; Select 仅是您真正需要的特定字段;
  2. Avoid using nulls in primary keys;避免在主键中使用空值;
  3. Surrogate primary keys are preferred.首选代理主键。

Update更新

Oooops... I missed phrase "Above table has no indexes" while reading question before.哎呀...我在之前阅读问题时错过了“Above table has no indexs”这句话。

Therefore only one recommendation: just create an index.因此只有一个建议:只创建一个索引。

You can make it faster by您可以通过以下方式使其更快

  • SELECT the specific item you want to reduce the result weight. SELECT 您要减少结果重量的特定项目。
  • In WHERE clause use the o_crd_score >650 in first place, crd_expiration_date is null in second place and crd_effective_date>to_date('20100801','YYYYMMDD') in the last在 WHERE 子句中,首先使用o_crd_score >650crd_expiration_date is null ,其次是crd_effective_date>to_date('20100801','YYYYMMDD')

So the query will be like.所以查询会是这样的。

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 

What I am doing here is that short circuiting the the records to the minimum so that the date check will be applied to the filtered out record.我在这里所做的是将记录短路到最低限度,以便将日期检查应用于过滤掉的记录。

Also you can make it fast by applying the INDEX on the table.您也可以通过在表格上应用 INDEX 来加快速度。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM