我在这里遇到问题。我使用的是Oracle 11g,我有这个问题:
SELECT /*+ PARALLEL(16) */
prdecdde,
prdenusi,
prdenpol,
prdeano,
prdedtpr
FROM stat_pro_det
WHERE prdeisin IS NULL AND PRDENUSI IS NOT NULL AND prdedprv = '20160114'
GROUP BY prdecdde,
prdenusi,
prdenpol,
prdeano,
prdedtpr;
我得到了下一个执行计划:
--------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 53229 | 2287K| | 3652 (4)| 00:00:01 |
| 1 | HASH GROUP BY | | 53229 | 2287K| 3368K| 3652 (4)| 00:00:01 |
|* 2 | TABLE ACCESS BY INDEX ROWID| STAT_PRO_DET | 53229 | 2287K| | 3012 (3)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | STAT_PRO_DET_08 | 214K| | | 626 (4)| 00:00:01 |
--------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("PRDENUSI" IS NOT NULL AND "PRDEISIN" IS NULL)
3 - access("PRDEDPRV"='20160114')
Note
-----
- Degree of Parallelism is 1 because of hint
我仍然有很多CPU成本。 STAT_PRO_DET_08索引是:
CREATE INDEX STAT_PRO_DET_08 ON STAT_PRO_DET(PRDEDPRV)
我试图将PRDEISIN和PRDENUSI添加到索引中,首先选择最具选择性,但结果最差。
这张表有1.28亿条记录(是的......也许我们需要一个PARTITION TABLE)。但我暂时不能对表格进行分区。
其他吸烟有哪些?一个不同的指数可以获得更好的结果,或者不能做得更好?
提前致谢!!!!
EDIT1: 伙计们......非常感谢你的帮助。特别是@Marmite 我有下一个问题:将这两个查询添加到主题中。为每个索引创建一个索引,或者我可以使用索引来解决这三个查询中的性能问题吗?
SELECT /*+ PARALLEL(16) */
prdecdde,
prdenuau,
prdenpol,
prdeano,
prdedtpr
FROM stat_pro_det
WHERE prdeisin IS NULL AND PRDENUSI IS NULL AND prdedprv = '20160114'
GROUP BY prdecdde,
prdenuau,
prdenpol,
prdeano,
prdedtpr;
和
SELECT /*+ PARALLEL(16) */
prdeisin, prdenuau
FROM stat_pro_det, mtauto
WHERE prdedprv = '20160114' AND prdenuau = autonuau AND autoisin IS NULL
GROUP BY prdenuau, prdeisin
答案 0 :(得分:3)
首先,您不妨将查询重写为:
SELECT /*+ PARALLEL(16) */ DISTINCT
prdecdde, prdenusi, prdenpol, prdeano, prdedtpr
FROM stat_pro_det
WHERE prdeisin IS NULL AND PRDENUSI IS NOT NULL AND prdedprv = '20160114';
(这个更短,可以更容易地更改您感兴趣的列列表。)
此查询的最佳索引是:stat_pro_det(prdedprv, prdeisin, prdenusi, prdecdde, prdenpol, prdeano, prdedtpr)
。
前三列对WHERE
子句很重要,并过滤数据。其余列“覆盖”查询,这意味着索引本身可以解析查询而无需访问数据页。
答案 1 :(得分:2)
首先做出以下决定:
Generall规则是索引访问对于少量访问的记录工作正常,但是在大数量的情况下扩展性不佳。
因此,最好的方法是测试所有选项并查看结果。
对于并行FULL TABLE SCAN
使用如下提示(替换 tab 的表名或别名)
SELECT /*+ FULL(tab) PARALLEL(16) */
这可以更好地扩展,但对于少量记录来说不是即时的。
索引访问
请注意,此不会并行执行。在问题中查看解释计划中的注释。
定义包含所有列的索引(由Gordon提出),您将执行(顺序)索引范围扫描而无需访问该表。
如上所述 - 根据访问的密钥数量,这将是快速或慢速的。
并行索引访问
您需要定义GLOBAL分区索引
create index tab_idx on tab (col3,col2,col1,col4,col5)
global partition by hash (col3,col2,col1,col4,col5) PARTITIONS 16;
比提示
SELECT /*+ INDEX(tab tab_idx) PARALLEL_INDEX(tab,16) */
您将执行相同的索引范围扫描,但这次是并行执行。所以它有可能会对串行执行产生反应。如果你真的可以打开DOP 16,当然还有你的数据库硬件设置和配置......