1

假设名为 TABLE1 的表中有 10 行,而 TABLE2 中的另一个表中有一百万行,如果我对这两个表进行如下查询:

Select * from TABLE1 where some_column = 'some_value';

Select * from TABLE2 where some_column = 'some_value';

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

4

5 回答 5

2

我只想知道这两个查询会花费相同的时间

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

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

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

如果不确定是否完成了全表扫描或索引是否可用于查询,您可以为 SQL 语句创建执行计划

于 2013-04-30T07:13:21.527 回答
1

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

如果表没有被索引,查询 2 所花费的时间可能会相当长,因为查询处理器必须扫描整个 1.000.000 行才能找到满足 WHERE 子句的行。

于 2013-04-30T07:09:37.837 回答
0

正如已建议的那样,进行基准测试。一个简单的 - 2 个具有 10 和 300k 行的表 - 向我们展示了在您的条件具有高度选择性的情况下,没有巨大的差异(通过查询读取的 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
于 2013-04-30T07:35:07.840 回答
0

更准确地说,查询运行的速度取决于所使用的索引。在大多数(微不足道的)情况下,您将在表上设置一个主键,这会导致最简单的索引情况,表的每一行都有一个唯一的编号,然后可以对其进行比较,这就是占用时间的原因. 在这种情况下,所花费的时间取决于表中的行数,但是当表上有不同类型的索引时,这可能会有很大差异(是的,可以有多个;))

进一步阅读索引

于 2013-04-30T07:11:58.410 回答
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. 表“宽度”。宽表(包含许多列)的扫描速度比包含较少列的窄表要慢。

于 2013-04-30T07:48:03.890 回答