Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 甲骨文选择,带“;“在(多个值)”中;不使用索引_Sql_Oracle_Performance_Optimization - Fatal编程技术网

Sql 甲骨文选择,带“;“在(多个值)”中;不使用索引

Sql 甲骨文选择,带“;“在(多个值)”中;不使用索引,sql,oracle,performance,optimization,Sql,Oracle,Performance,Optimization,Oracle(12.1)不使用真正有利的索引。 使用union all重写manuel查询有帮助,但确实很难看。 有什么想法吗 模式: 表“umsatz”,按“monat”的每个值进行分区(=年+月作为数字) 上的简单非唯一索引(monat,kundengruppe) 统计数据是可用的,并且是最新的 “monat”不是很有选择性(每个月有很多值),但“kundengruppe”列对其大多数值都有选择性。 “kundengruppe”具有混合柱状图,此处使用的具体值不会出现在表中(即,非常有选择

Oracle(12.1)不使用真正有利的索引。
使用
union all
重写manuel查询有帮助,但确实很难看。
有什么想法吗

模式:

  • 表“umsatz”,按“monat”的每个值进行分区(=年+月作为数字)
  • 上的简单非唯一索引(monat,kundengruppe)
  • 统计数据是可用的,并且是最新的
  • “monat”不是很有选择性(每个月有很多值),但“kundengruppe”列对其大多数值都有选择性。
    “kundengruppe”具有混合柱状图,此处使用的具体值不会出现在表中(即,非常有选择性)-将其更改为很少出现的值不会改变任何东西。查询单个频繁出现的值会导致完整的表/分区扫描——在本例中这是可以的
查询(减少到相关的最小部分):

以及其执行计划:

------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                        | Name                       | Rows | Bytes | Cost | Time     |
------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                                 |                            |    1 |    14 | 3074 | 00:00:01 |
|   1 |   SORT AGGREGATE                                 |                            |    1 |    14 |      |          |
|   2 |    MAT_VIEW ACCESS BY GLOBAL INDEX ROWID BATCHED | UMSATZ_BUDGETBLATT         |    1 |    14 | 3074 | 00:00:01 |
| * 3 |     INDEX RANGE SCAN                             | UMSATZ_BUDGETBLATT_GRP_NUI |    1 |       | 3073 | 00:00:01 |
------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
------------------------------------------
* 3 - access("UB"."MONAT">=201701 AND "UB"."MONAT"<=201712)
* 3 - filter("UB"."KUNDENGRUPPE"=123 OR "UB"."KUNDENGRUPPE"=456 OR "UB"."KUNDENGRUPPE"=987)
.
我可以用语义等价的UNION ALL手动重写中的多个值:

SELECT SUM(u.umsatz_euro)
  FROM 
  (select * from umsatz u
    where u.kundengruppe = 123
   union all
   select * from umsatz u
    where u.kundengruppe = 456
   union all
   select * from umsatz u
    where u.kundengruppe = 987
  ) u
 WHERE u.monat BETWEEN 201701 AND 201712
执行计划三次使用索引,成本大大低于第一个计划(3000->14),Oracle甚至将“monat”谓词下推到每个选择中:

--------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                          | Name                       | Rows | Bytes | Cost | Time     |
--------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                                   |                            |    1 |    26 |   12 | 00:00:01 |
|   1 |   SORT AGGREGATE                                   |                            |    1 |    26 |      |          |
|   2 |    VIEW                                            |                            |    3 |    78 |   12 | 00:00:01 |
|   3 |     UNION-ALL                                      |                            |      |       |      |          |
|   4 |      MAT_VIEW ACCESS BY GLOBAL INDEX ROWID BATCHED | UMSATZ_BUDGETBLATT         |    1 |    14 |    4 | 00:00:01 |
| * 5 |       INDEX RANGE SCAN                             | UMSATZ_BUDGETBLATT_GRP_NUI |    1 |       |    3 | 00:00:01 |
|   6 |      MAT_VIEW ACCESS BY GLOBAL INDEX ROWID BATCHED | UMSATZ_BUDGETBLATT         |    1 |    14 |    4 | 00:00:01 |
| * 7 |       INDEX RANGE SCAN                             | UMSATZ_BUDGETBLATT_GRP_NUI |    1 |       |    3 | 00:00:01 |
|   8 |      MAT_VIEW ACCESS BY GLOBAL INDEX ROWID BATCHED | UMSATZ_BUDGETBLATT         |    1 |    14 |    4 | 00:00:01 |
| * 9 |       INDEX RANGE SCAN                             | UMSATZ_BUDGETBLATT_GRP_NUI |    1 |       |    3 | 00:00:01 |
--------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
------------------------------------------
* 5 - access("UB"."MONAT">=201701 AND "UB"."KUNDENGRUPPE"=123 AND "UB"."MONAT"<=201712)
* 5 - filter("UB"."KUNDENGRUPPE"=123)
* 7 - access("UB"."MONAT">=201701 AND "UB"."KUNDENGRUPPE"=456 AND "UB"."MONAT"<=201712)
* 7 - filter("UB"."KUNDENGRUPPE"=456)
* 9 - access("UB"."MONAT">=201701 AND "UB"."KUNDENGRUPPE"=987 AND "UB"."MONAT"<=201712)
* 9 - filter("UB"."KUNDENGRUPPE"=987)
该计划使用(慢速)索引跳过扫描:

------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                        | Name                       | Rows | Bytes | Cost | Time     |
------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                                 |                            |    1 |    14 |  955 | 00:00:01 |
|   1 |   SORT AGGREGATE                                 |                            |    1 |    14 |      |          |
|   2 |    MAT_VIEW ACCESS BY GLOBAL INDEX ROWID BATCHED | UMSATZ_BUDGETBLATT         | 1769 | 24766 |  955 | 00:00:01 |
| * 3 |     INDEX SKIP SCAN                              | UMSATZ_BUDGETBLATT_GRP_NUI | 1769 |       |   36 | 00:00:01 |
------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
------------------------------------------
* 3 - access("UB"."MONAT">=201701 AND "UB"."KUNDENGRUPPE"=TO_NUMBER(:A) AND "UB"."MONAT"<=201712)
* 3 - filter("UB"."KUNDENGRUPPE"=TO_NUMBER(:A))
------------------------------------------------------------------------------------------------------------------------
|Id |操作|名称|行|字节|成本|时间|
------------------------------------------------------------------------------------------------------------------------
|0 | SELECT语句| | 1 | 14 | 955 | 00:00:01|
|1 |对骨料进行排序| | 1 | 14 | ||
|2 |按全局索引ROWID批处理的MAT|U视图访问| UMSATZ|U预算板| 1769 | 24766 | 955 | 00:00:01|
|*3 |索引跳过扫描| UMSATZ | U预算板| U GRP | U NUI | 1769 | 36 | 00:00:01|
------------------------------------------------------------------------------------------------------------------------
谓词信息(由操作id标识):
------------------------------------------

*3-访问(“UB”。“MONAT”>=201701和“UB”。“KUNDENGRUPPE”=TO_编号(:A)和“UB”。“MONAT”复合索引最终与所有索引类似,一个键后跟数据(rowid)

因此(monat,kundengruppe)上的索引在有序索引结构中的键在概念上类似于:

201701-123
201701-...
201701-...
201701-456
201701-...
201701-...
201701-987
201701-...
201701-...
201701-...
201701-...
201712-123
201712-...
201712-...
201712-456
201712-...
201712-...
201712-...
201712-987
201712-...
因此,当涉及到查询时,请记住这一点:

WHERE u.monat BETWEEN 201701 AND 201712 AND u.kundengruppe = 123
我有一个逻辑起点(201701-123)和逻辑终点(201702-123)

当我们向优化器演示以下内容时:

WHERE u.monat BETWEEN 201701 AND 201712 AND u.kundengruppe in (123,456,789)
这是一个更难提出的最佳索引使用策略

理想情况下,它可以在kundengruppe中对列表进行排序,并使用-key的索引访问,介于201701-[min list value]和201712-[max list value]之间,或者像手动重写一样将其分成3个单独的访问

但在这两种情况下,就访问成本而言,这都是一个艰难的命题,也就是说,它是使用的最佳选项吗,因为(根据我的索引键列表),可能散布在感兴趣的索引键之间的值的数量很难估计。类似地,在哪一点上,您会放弃将in列表拆分为各个部分的策略。如果第二个谓词是:

u.kundengruppe in (123,456,... [500 more values]...789)
在这种情况下,您可能不想将其拆分


很抱歉,我没有什么好的解决方案,但最终,您对优化器和(自动)查询转换的要求是有限的。

我根据康纳的回答所引发的想法进行了一些测试。结果回答了我自己的问题

我将索引中的列顺序更改为
(kundengruppe,monat)
,即选择性列排在第一位(“monat”只有大约30个不同的值,但被放在第一位,因为它是分区属性——在这种情况下,对于良好的访问是一个错误的想法)

现在,计划和成本看起来与预期一致:

SELECT SUM(u.umsatz_euro)
  FROM umsatz u
 WHERE u.monat BETWEEN 201701 AND 201712
   AND u.kundengruppe IN (123,456,987)

-------------------------------------------------------------------------------------------------------------------------
|Id |操作|名称|行|字节|成本|时间|
-------------------------------------------------------------------------------------------------------------------------
|0 |选择语句| | 1 | 14 | 6 | 00:00:01|
|1 |对骨料进行排序| | 1 | 14 | ||
|2 | INLIST迭代器| | | | ||
|3 |按全局索引ROWID批处理的MAT|U视图访问| UMSATZ|U预算板| 1 | 14 | 6 | 00:00:01|
|*4 |索引范围扫描| UMSATZ | U预算板| U GRP | U NUI | 1 | 5 | 00:00:01|
-------------------------------------------------------------------------------------------------------------------------
谓词信息(由操作id标识):
------------------------------------------
*4-访问((“UB”。“KUNDENGRUPPE”=123或“UB”。“KUNDENGRUPPE”=456或“UB”。“KUNDENGRUPPE”=987)和“UB”。“MONAT”>=201701和“UB”。“MONAT”=201701和

“UB”。“MONAT”最近是否运行了表的聚集统计信息?使用索引提示的选项如何?统计信息是最新的(请参阅编辑的文本)。索引提示不会更改任何内容,可能是因为索引已被使用,但仅用于“MONAT”列。是否可以使用OEM?索引
WHERE u.monat BETWEEN 201701 AND 201712 AND u.kundengruppe in (123,456,789)
u.kundengruppe in (123,456,... [500 more values]...789)
SELECT SUM(u.umsatz_euro)
  FROM umsatz u
 WHERE u.monat BETWEEN 201701 AND 201712
   AND u.kundengruppe IN (123,456,987)
-------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                         | Name                       | Rows | Bytes | Cost | Time     |
-------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                                  |                            |    1 |    14 |    6 | 00:00:01 |
|   1 |   SORT AGGREGATE                                  |                            |    1 |    14 |      |          |
|   2 |    INLIST ITERATOR                                |                            |      |       |      |          |
|   3 |     MAT_VIEW ACCESS BY GLOBAL INDEX ROWID BATCHED | UMSATZ_BUDGETBLATT         |    1 |    14 |    6 | 00:00:01 |
| * 4 |      INDEX RANGE SCAN                             | UMSATZ_BUDGETBLATT_GRP_NUI |    1 |       |    5 | 00:00:01 |
-------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
------------------------------------------
* 4 - access(("UB"."KUNDENGRUPPE"=123 OR "UB"."KUNDENGRUPPE"=456 OR "UB"."KUNDENGRUPPE"=987) AND "UB"."MONAT">=201701 AND "UB"."MONAT"<=201712)
-------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                         | Name                       | Rows | Bytes | Cost | Time     |
-------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                                  |                            |    1 |    14 | 1518 | 00:00:01 |
|   1 |   SORT AGGREGATE                                  |                            |    1 |    14 |      |          |
|   2 |    INLIST ITERATOR                                |                            |      |       |      |          |
|   3 |     MAT_VIEW ACCESS BY GLOBAL INDEX ROWID BATCHED | UMSATZ_BUDGETBLATT         | 2664 | 37296 | 1518 | 00:00:01 |
| * 4 |      INDEX RANGE SCAN                             | UMSATZ_BUDGETBLATT_GRP_NUI | 2900 |       |   12 | 00:00:01 |
-------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
------------------------------------------
* 4 - access(("UB"."KUNDENGRUPPE"=1899 OR "UB"."KUNDENGRUPPE"=2032 OR "UB"."KUNDENGRUPPE"=2160 OR "UB"."KUNDENGRUPPE"=2165 OR "UB"."KUNDENGRUPPE"=5048) AND "UB"."MONAT">=201701 AND
  "UB"."MONAT"<=201712)
------------------------------------------------------------------------------------------------
| Id  | Operation                   | Name               | Rows   | Bytes   | Cost  | Time     |
------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |                    |      1 |      14 | 12494 | 00:00:01 |
|   1 |   SORT AGGREGATE            |                    |      1 |      14 |       |          |
|   2 |    PARTITION RANGE ITERATOR |                    | 117769 | 1648766 | 12494 | 00:00:01 |
| * 3 |     MAT_VIEW ACCESS FULL    | UMSATZ_BUDGETBLATT | 117769 | 1648766 | 12494 | 00:00:01 |
------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
------------------------------------------
* 3 - filter("UB"."KUNDENGRUPPE"=5047 AND "UB"."MONAT"<=201712)