当前位置: 首页 > 面试题库 >

性能问题:select s。*与select *之间的区别

盛骏祥
2023-03-14
问题内容

最近,我在查询性能方面遇到了一些问题。经过长时间的努力,我终于发现带有select前缀的查询如下:

    SELECT sth.* FROM Something as sth...

是慢300倍,然后以这种方式启动查询:

    SELECT * FROM Something as sth..

有人可以帮我吗,为什么呢?关于此的一些外部文档将非常有用。

用于测试的表是:

SALES_UNIT 表包含一些基本的信息 自动售货机
节点,例如名称等。唯一的关联是表SALES_UNIT_TYPE,例如ManyToOne。主键是ID和字段VALID_FROM_DTTM,它是日期。

SALES_UNIT_RELATION 包含销售单位节点之间的关系PARENT-
CHILD。由SALES_UNIT_PARENT_ID,SALES_UNIT_CHILD_ID和VALID_TO_DTTM /
VALID_FROM_DTTM组成。没有与任何表的关联。此处的PK是..PARENT_ID,.. CHILD_ID和VALID_FROM_DTTM

我使用的实际查询是:

    SELECT s.* 
    FROM   sales_unit s LEFT JOIN sales_unit_relation r 
               on (s.sales_unit_id = r.sales_unit_child_id) 
    WHERE  r.sales_unit_child_id IS NULL

    SELECT  * 
    FROM    sales_unit s LEFT JOIN sales_unit_relation r 
               on (s.sales_unit_id = r.sales_unit_child_id) 
    WHERE   r.sales_unit_child_id  IS NULL

相同的查询,都使用左连接,唯一的区别是选择。


问题答案:

当然,这是两个不同的查询。计划可以随着选择的不同而改变。即在某事上。*可能是在左侧联接表上选择了全/快速全索引扫描。第一次可能是全表扫描。

为了进一步帮助您,我们可以看看这些计划吗?最好在SQL * PLUS中执行此操作

set timing on
set autotrace on traceonly

select s.* from sales_unit s left join sales_unit_relation r on (s.sales_unit_id = r.sales_unit_child_id) where r.sales_unit_child_id is null;

select * from sales_unit s left join sales_unit_relation r on (s.sales_unit_id = r.sales_unit_child_id) where r.sales_unit_child_id is null;

编辑

根据您的解释计划,您看到每一步的CARDINALITY = 1吗?表格为空时,您已经收集了统计信息!看到这个:

SQL> select s.* from sales_unit s left join sales_unit_relation r on (s.sales_unit_id = r.child_sales_unit_id) where r.child_sales_unit_id is null;

no rows selected

Elapsed: 00:00:03.19

Execution Plan
----------------------------------------------------------
Plan hash value: 1064670292

------------------------------------------------------------------------------------
| Id  | Operation          | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |               |     1 |    48 |    27  (86)| 00:00:01 |
|   1 |  NESTED LOOPS ANTI |               |     1 |    48 |    27  (86)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| SALES_UNIT    |     1 |    35 |     2   (0)| 00:00:01 |
|*  3 |   INDEX RANGE SCAN | SALES_REL_IX1 |     1 |    13 |    25  (92)| 00:00:01 |
------------------------------------------------------------------------------------

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

   3 - access("S"."SALES_UNIT_ID"="R"."CHILD_SALES_UNIT_ID")


Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
     200314  consistent gets
       2220  physical reads
          0  redo size
        297  bytes sent via SQL*Net to client
        339  bytes received via SQL*Net from client
          1  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          0  rows processed

因此看到它使用了200314 IO,并花费了几秒钟。还要在每一步上看到ROWS = 1(即完整扫描)。.let收集统计信息:

SQL> begin dbms_stats.gather_table_stats(user, 'SALES_UNIT', degree=>8, cascade=>true); end;
  2  /

PL/SQL procedure successfully completed.

SQL> begin dbms_stats.gather_table_stats(user, 'SALES_UNIT_RELATION', degree=>8, cascade=>true); end;
  2  /

PL/SQL procedure successfully completed.

然后重新运行:SQL>从sales_unit的左选择s。*加入(s.sales_unit_id =
r.child_sales_unit_id)上的sales_unit_relation r,其中r.child_sales_unit_id为null;

no rows selected

Elapsed: 00:00:00.84

Execution Plan
----------------------------------------------------------
Plan hash value: 2005864719

-----------------------------------------------------------------------------------------------
| Id  | Operation             | Name          | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |               |   912 | 18240 |       |  1659   (3)| 00:00:20 |
|*  1 |  HASH JOIN ANTI       |               |   912 | 18240 |  2656K|  1659   (3)| 00:00:20 |
|   2 |   TABLE ACCESS FULL   | SALES_UNIT    |   100K|  1472K|       |    88   (3)| 00:00:02 |
|   3 |   INDEX FAST FULL SCAN| SALES_REL_IX1 |   991K|  4841K|       |   618   (3)| 00:00:08 |
-----------------------------------------------------------------------------------------------

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

   1 - access("S"."SALES_UNIT_ID"="R"."CHILD_SALES_UNIT_ID")


Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
       2537  consistent gets
          0  physical reads
          0  redo size
        297  bytes sent via SQL*Net to client
        339  bytes received via SQL*Net from client
          1  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          0  rows processed

SQL>

现在我们只使用了2537个Gets,该计划显示了正确的ROWS和HASH联接(更好地满足了我们的需求)。我的测试表可能比您的实际测试表小,这就是为什么时间更短的原因



 类似资料:
  • 问题内容: 哪一个性能更好 或者 ? 问题答案: 两者执行相同,因为从不评估EXISTS中的SELECT子句。您可以使用以下方法进行测试: 那应该触发除以零的错误,但是不会。 我个人更喜欢使用NULL,因为很明显表中没有引用任何东西,因此其他人更容易看到。选择一个值,例如第二个示例中的INT数字1,如果不熟悉EXISTS子句,可能会导致对所发生情况的假设。

  • 问题内容: VisualVM有两个单独的选项卡,用于采样和分析。在VisualVM中采样和配置文件有什么区别? 问题答案: 意味着要进行大量的线程转储并分析堆栈跟踪。这通常更快,不需要字节码中的运行时更改(这可能会破坏它),但准确性也较低。 表示检测您的类和方法,以便它们在运行时“报告”。这是更准确的,因为它不仅计数完成转储时捕获的那些方法,而且还计算每次检测的方法调用。但是,检测意味着更改了您的

  • 问题内容: 当您使用 BeautifulSoup 抓取网站的特定部分时,您可以使用 和或 。 和方法之间有区别吗?(例如,性能或灵活性等)还是相同? 问题答案: 总结评论: select 查找多个实例并返回一个列表, find 查找第一个实例,因此它们不会执行相同的操作。 select_one 将等同于 find 。 我链接时,标签或使用几乎总是使用CSS选择 tag.classname ,如果寻

  • 问题内容: 我正在尝试对我们的客户代码进行基准测试。因此,我决定编写一个多线程程序来对我的客户端代码进行基准测试。我正在尝试测量下面的方法需要多少? 因此,下面是我编写的用于对上述方法进行基准测试的多线程代码。在两种情况下,我看到了很多变化- 1)首先,使用和来处理多线程代码。我得到95%的。我正在使用- 2)但是,如果我运行相同的程序以使用- 代替 当我使用运行代码时,我得到95%,比上面的数字

  • 我们在ignite中面临着间歇性的性能问题,响应时间变得非常高,我们在日志中看到了下面的错误。我们有10个索引列,我没有看到索引有任何问题,因为“where”子句中的所有列都被索引了。联接发生在具有亲和性共定位的字段上,这意味着联接只发生在特定节点中的数据上,而不发生在Across ;节点上。 请让我知道你是否能在这方面提供任何帮助。  > Apache Ignite版本:2.7.5 启用Igni

  • 基本方法 双指针(滑动窗口) 定长滑动 变长滑动 扫描线算法 会议室 LintCode - 920. 会议室 问题描述 给定一系列的会议时间间隔,包括起始和结束时间[[s1,e1],[s2,e2],…(si < ei), 确定一个人是否可以参加所有会议。 样例 给定区间=[[0,30],[5,10],[15,20]],返回false。 思路 排序后判断左右区间 C++ //class Inter