Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/10.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
oraclesql如何在不相关子查询中进行优化_Sql_Oracle_Query Optimization - Fatal编程技术网

oraclesql如何在不相关子查询中进行优化

oraclesql如何在不相关子查询中进行优化,sql,oracle,query-optimization,Sql,Oracle,Query Optimization,我有以下查询执行得很差: select distinct u.uuid u.user_name, u.key from request req join int_user u on u.uuid = req.user_uuid join int_right r on r.uuid = req.right_uuid where r.uuid in ( select r2.uuid

我有以下查询执行得很差:

select 
    distinct 
    u.uuid
    u.user_name,
    u.key

    from request req 
         join int_user u on u.uuid = req.user_uuid
         join int_right r on r.uuid = req.right_uuid

    where r.uuid in (
            select r2.uuid from int_right r2
                    where 
                            (
                                lower(r2.right_name) like '%keyword%'
                                or lower(r2.right_key) like '%keyword%'
                            )

                    )
select 
    distinct 
    u.uuid
    u.user_name,
    u.key

    from request req 
         join int_user u on u.uuid = req.user_uuid
         join int_right r on r.uuid = req.right_uuid 
    Where (lower(r.right_name) like '%keyword%' or lower(r.right_key) like '%keyword%')
子查询是不相关的,它通常只返回几行,有时只返回一行。 现在我不明白为什么如果我接受子查询并单独执行它,然后接受结果列表并使用IN运算符将其静态添加到外部查询,那么它将执行得非常好,从3-6秒执行时间下降到0.05秒

r.uuid in ('value1', 'value2', 'value3')
select 
    distinct 
    u.uuid
    u.user_name,
    u.key

    from request req 
         join int_user u on u.uuid = req.user_uuid
         join int_right r on r.uuid = req.right_uuid 
    Where (lower(r.right_name) like '%keyword%' or lower(r.right_key) like '%keyword%')
如何让oracle先执行子查询,然后将结果集应用于外部查询

select 
    distinct 
    u.uuid
    u.user_name,
    u.key

    from request req 
         join int_user u on u.uuid = req.user_uuid
         join int_right r on r.uuid = req.right_uuid 
    Where (lower(r.right_name) like '%keyword%' or lower(r.right_key) like '%keyword%')
几点注意:

select 
    distinct 
    u.uuid
    u.user_name,
    u.key

    from request req 
         join int_user u on u.uuid = req.user_uuid
         join int_right r on r.uuid = req.right_uuid 
    Where (lower(r.right_name) like '%keyword%' or lower(r.right_key) like '%keyword%')
请求表非常庞大,大约有7百万行 Int_右表-约10K行 Int_用户表-大约10万行 从执行计划来看,oracle似乎对所有表进行了全面扫描。成本和基数是非常大的要求表。 同样有趣的是,即使我的子查询将针对某个搜索条件返回一行,查询仍然很慢,但是如果我将IN运算符替换为equals=则查询变得非常快,成本也很低。在这种情况下,oracle似乎只会在int_right表中执行完全扫描,而对于其他表,它会执行唯一或范围扫描

select 
    distinct 
    u.uuid
    u.user_name,
    u.key

    from request req 
         join int_user u on u.uuid = req.user_uuid
         join int_right r on r.uuid = req.right_uuid 
    Where (lower(r.right_name) like '%keyword%' or lower(r.right_key) like '%keyword%')

我还尝试了此查询的其他变体,如直接将条件添加到外部查询、使用exists或关联子查询,但无论如何都很慢。

为什么需要子查询

select 
    distinct 
    u.uuid
    u.user_name,
    u.key

    from request req 
         join int_user u on u.uuid = req.user_uuid
         join int_right r on r.uuid = req.right_uuid 
    Where (lower(r.right_name) like '%keyword%' or lower(r.right_key) like '%keyword%')
相同条件可通过两种不同方式应用:

select 
    distinct 
    u.uuid
    u.user_name,
    u.key

    from request req 
         join int_user u on u.uuid = req.user_uuid
         join int_right r on r.uuid = req.right_uuid 
    Where (lower(r.right_name) like '%keyword%' or lower(r.right_key) like '%keyword%')
联合

select 
    distinct 
    u.uuid
    u.user_name,
    u.key

    from request req 
         join int_user u on u.uuid = req.user_uuid
         join int_right r on r.uuid = req.right_uuid 
    Where (lower(r.right_name) like '%keyword%' or lower(r.right_key) like '%keyword%')
在哪里

select 
    distinct 
    u.uuid
    u.user_name,
    u.key

    from request req 
         join int_user u on u.uuid = req.user_uuid
         join int_right r on r.uuid = req.right_uuid 
    Where (lower(r.right_name) like '%keyword%' or lower(r.right_key) like '%keyword%')

两者都会导致更快的查询,尽管我不能100%确定哪一个1会更快。据我所知,连接中的连接将更快…

通常不能通过查看文本来调整SQL语句,除非代码中存在根本缺陷,例如缺少连接条件等。对于Oracle,最有效的方法之一是:

select 
    distinct 
    u.uuid
    u.user_name,
    u.key

    from request req 
         join int_user u on u.uuid = req.user_uuid
         join int_right r on r.uuid = req.right_uuid 
    Where (lower(r.right_name) like '%keyword%' or lower(r.right_key) like '%keyword%')
1使用以下附加提示执行有问题的语句

select 
    distinct 
    u.uuid
    u.user_name,
    u.key

    from request req 
         join int_user u on u.uuid = req.user_uuid
         join int_right r on r.uuid = req.right_uuid 
    Where (lower(r.right_name) like '%keyword%' or lower(r.right_key) like '%keyword%')
select /*+ gather_plan_statistics */ ... <rest of query>
这样,您将:

select 
    distinct 
    u.uuid
    u.user_name,
    u.key

    from request req 
         join int_user u on u.uuid = req.user_uuid
         join int_right r on r.uuid = req.right_uuid 
    Where (lower(r.right_name) like '%keyword%' or lower(r.right_key) like '%keyword%')
a查看所使用的真实执行计划

select 
    distinct 
    u.uuid
    u.user_name,
    u.key

    from request req 
         join int_user u on u.uuid = req.user_uuid
         join int_right r on r.uuid = req.right_uuid 
    Where (lower(r.right_name) like '%keyword%' or lower(r.right_key) like '%keyword%')
b获取计划中每个步骤的估计/实际行源计数。如果估计值与实际值之间的差异很大,那么这通常是您关注的重点,因为优化器很可能没有足够或准确的信息来处理这一问题

select 
    distinct 
    u.uuid
    u.user_name,
    u.key

    from request req 
         join int_user u on u.uuid = req.user_uuid
         join int_right r on r.uuid = req.right_uuid 
    Where (lower(r.right_name) like '%keyword%' or lower(r.right_key) like '%keyword%')
比如说

select 
    distinct 
    u.uuid
    u.user_name,
    u.key

    from request req 
         join int_user u on u.uuid = req.user_uuid
         join int_right r on r.uuid = req.right_uuid 
    Where (lower(r.right_name) like '%keyword%' or lower(r.right_key) like '%keyword%')
SQL> select /*+ gather_plan_statistics */ count(dname)
  2  from  scott.emp e, scott.dept d
  3  where e.sal <= 1500
  4  and  d.deptno = e.deptno;

COUNT(DNAME)
------------
           7

1 row selected.

SQL> select * from table(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST'));

PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------------------
SQL_ID  c1cb4s8b141h8, child number 0
-------------------------------------
select /*+ gather_plan_statistics */ count(dname) from  scott.emp e,
scott.dept d where e.sal <= 1500 and  d.deptno = e.deptno

Plan hash value: 3037575695

---------------------------------------------------------------------------------------------------
| Id  | Operation                     | Name    | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
---------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT              |         |      1 |        |      1 |00:00:00.01 |       9 |
|   1 |  SORT AGGREGATE               |         |      1 |      1 |      1 |00:00:00.01 |       9 |
|   2 |   MERGE JOIN                  |         |      1 |      3 |      7 |00:00:00.01 |       9 |
|   3 |    TABLE ACCESS BY INDEX ROWID| DEPT    |      1 |      4 |      4 |00:00:00.01 |       2 |
|   4 |     INDEX FULL SCAN           | DEPT_PK |      1 |      4 |      4 |00:00:00.01 |       1 |
|*  5 |    SORT JOIN                  |         |      4 |      3 |      7 |00:00:00.01 |       7 |
|*  6 |     TABLE ACCESS FULL         | EMP     |      1 |      3 |      7 |00:00:00.01 |       7 |
---------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   5 - access("D"."DEPTNO"="E"."DEPTNO")
       filter("D"."DEPTNO"="E"."DEPTNO")
   6 - filter("E"."SAL"<=1500)

在第6行,您可以看到优化器估计了3行,但实际上得到了7行。较大的差异表明需要调查的区域。

很抱歉输入错误。更正,谢谢。为什么需要子查询?我认为,子查询中的where子句可以作为外部查询中的where子句。是的,但在大多数情况下,如果在外部查询中使用where子句,我会获得相同的性能。如果搜索条件为长20-30个字符,则子查询的性能更好。您需要提供短搜索条件和长搜索条件的执行计划,以及有无子查询的执行计划,以便我们了解速度缓慢是否有原因。感谢您的答复,但已尝试过此操作,但不会提高性能。当搜索条件较小时,我可以获得相同的性能,但是当搜索条件较大(如20-30个字符)时,子查询的性能会更好,无法解释为什么..@DimaSendrea连接条件上有索引吗?如果有帮助的话,也可以在存在的地方尝试。[.
select 
    distinct 
    u.uuid
    u.user_name,
    u.key

    from request req 
         join int_user u on u.uuid = req.user_uuid
         join int_right r on r.uuid = req.right_uuid 
    Where (lower(r.right_name) like '%keyword%' or lower(r.right_key) like '%keyword%')