[英]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
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_score
和crd_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:一般问题很常见,并在之前的答案中提到:
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您可以通过以下方式使其更快
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 lasto_crd_score >650
, crd_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.