SQL查询提供结果所花费的时间是否取决于表中的总行数或结果的最终行数?

时间:2013-04-30 07:06:12

标签: sql oracle

假设一个名为TABLE1的表中有10行,而TABLE2中的另一个表中有一百万行,如果我在这两个表上触发查询,如下所示:

Select * from TABLE1 where some_column = 'some_value';

Select * from TABLE2 where some_column = 'some_value';

我知道在这两种情况下我只会得到满足where子句的2行,那么获得结果的时间差异是多少。我不想在数字中得到任何确切的答案。我只是想知道两个查询会花费相同的时间,因为最终结果只有2行满足条件,或者所花费的时间取决于表中存在的总行数。

5 个答案:

答案 0 :(得分:2)

  

我只是想知道两个查询会花费同一时间

此类问题的一般建议是:做基准测试

  • 创建一个测试数据库,其中包含您以后在生产系统中预期的数据量(您可以使用简单的PL / SQL脚本或任何其他支持数据库连接的编程环境轻松完成此操作)。
  • 然后,创建一个小应用程序(理想情况下,在稍后执行查询的同一编程环境中)执行查询(理想情况下多次)并测量所需的时间。根据结果​​,您可以采取进一步行动。

在您的具体情况下,它在很大程度上取决于some_column列上是否有索引。如果没有索引,数据库需要执行全表扫描,这意味着对所有行进行线性搜索。如果列上有索引,则查询不应该花费很多不同的时间。

如果怀疑是否完成了全表扫描或者是否可以将索引用于查询,则可以为SQL语句创建execution plan

答案 1 :(得分:1)

这完全取决于表的索引方式。如果some_column上有索引,则两个查询所花费的时间大致相同(对于table2来说可能稍慢一些,因为table1的索引很可能由于较小的大小而驻留在内存中)。

如果表没有编入索引,查询2所用的时间可能会大得多,因为查询处理器必须扫描整个1.000.000行才能找到满足WHERE子句的行。

答案 2 :(得分:0)

更准确地说,查询运行的速度取决于所使用的索引。 在大多数(琐碎的)情况下,你将在你的桌子上设置一个主键,这将导致最简单的索引情况,你的表中的每一行都有一个唯一的数字,然后它可以被比较,这就是占用时间的东西。在这种情况下,所花费的时间取决于表中的行数,但当您在表上有不同类型的索引时,这可能会有很大差异(是的,可以有多个;)

进一步阅读indexes

答案 3 :(得分:0)

根据建议,做基准测试。一个简单的 - 一个包含10行和300k行的2个表 - 向我们显示,如果您的条件具有高度选择性,则没有太大的区别(2个对4个数据库块通过查询读取)。

15:22:14 HR@sandbox> ed
Wrote file S:\spool\sandbox\BUFFER_HR_42.sql

  1  create table table1 as
  2  select decode(rownum, 5, 6, 10, 6, mod(rownum, 5)) as value from dual
  3* connect by rownum <= 10
15:22:26 HR@sandbox> /

Table created.

Elapsed: 00:00:00.16
15:23:52 HR@sandbox> ed
Wrote file S:\spool\sandbox\BUFFER_HR_42.sql

  1   create table table2 as
  2   select decode(rownum, 1e3, 6, 5e4, 6, mod(rownum, 5)) as value from dual
  3*  connect by rownum <= 3e5
15:23:59 HR@sandbox> /

Table created.

Elapsed: 00:00:03.10
15:24:03 HR@sandbox> create index ix_t2_val on table2(value);

Index created.

Elapsed: 00:00:02.11
15:24:12 HR@sandbox> create index ix_t1_val on table1(value);

Index created.

Elapsed: 00:00:00.05
15:24:16 HR@sandbox> exec dbms_stats.gather_table_stats('hr','table1');

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.93
15:25:14 HR@sandbox> exec dbms_stats.gather_table_stats('hr','table2');

PL/SQL procedure successfully completed.

Elapsed: 00:00:02.19
15:25:18 HR@sandbox> select /*+index(table1 ix_t1_val)*/ * from table1 where value = 6;

Elapsed: 00:00:00.01

Execution Plan
----------------------------------------------------------
Plan hash value: 1719610244

------------------------------------------------------------------------------
| Id  | Operation        | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------
|   0 | SELECT STATEMENT |           |     2 |     6 |     1   (0)| 00:00:01 |
|*  1 |  INDEX RANGE SCAN| IX_T1_VAL |     2 |     6 |     1   (0)| 00:00:01 |
------------------------------------------------------------------------------

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

   1 - access("VALUE"=6)


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

15:25:34 HR@sandbox> select /*+index(table1 ix_t2_val)*/ * from table2 where value = 6;

Elapsed: 00:00:00.02

Execution Plan
----------------------------------------------------------
Plan hash value: 4026617716

------------------------------------------------------------------------------
| Id  | Operation        | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------
|   0 | SELECT STATEMENT |           | 50000 |   146K|    99   (0)| 00:00:02 |
|*  1 |  INDEX RANGE SCAN| IX_T2_VAL | 50000 |   146K|    99   (0)| 00:00:02 |
------------------------------------------------------------------------------

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

   1 - access("VALUE"=6)


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

答案 4 :(得分:0)

大多数其他答案都将索引视为影响查询性能。虽然这是一个很大的问题,但它不仅仅是索引会影响查询所用的时间长度。

在其他五个案例中,没有所有索引:

  1. 分区表:如果在some_column上对一个表进行了分区,则Oracle可能只扫描单个分区而不是整个表。这称为分区修剪 - Oracle消除了它知道赢得的分区,并且不包含查询中所需的任何数据。请参阅http://docs.oracle.com/cd/B10501_01/server.920/a96524/c12parti.htm#429785

  2. 并行全表扫描:如果启用了并行查询,Oracle可以动态地将表分解为粒度,并行进程可以扫描每个表以查找您正在寻找的值。请参阅http://docs.oracle.com/cd/A97630_01/server.920/a96524/c20paral.htm#6346

  3. 物理磁盘上的数据位置:不同的物理存储系统具有不同的性能特征。 DBA可以将某些历史数据表移动到相对缓慢,廉价的存储上,而其他表明确地移动到相对昂贵的快速存储中。

  4. Oracle缓存:表的数据已经可以在内存中,由Oracle自动或手动固定。这肯定会影响表现。

  5. 表&#34;宽度&#34;。宽表(包含许多列)将比包含较少列的窄表扫描更慢。