sql - 为什么这个查询这么慢?

标签 sql oracle indexing

我有表 FOO 和 BAR。 FOO 有一个 BAR PK 的外键。

当我执行以下查询时,它需要几秒钟。

select foo.name, foo.description, bar.quadrant from FOO, BAR
where FOO.BAR_ID = BAR.BAR_ID

这是我的解释计划:
OPERATION        OBJECT_NAME     OPTIONS     COST 
SELECT STATEMENT                                 39 
 HASH JOIN                                       39 
  TABLE ACCESS   BAR             FULL            2 
  TABLE ACCESS   FOO             FULL            36 

FOO 中有 6000 条记录,而 BAR 只有 5 条记录。 BAR_ID 列是一个 NUMBER。

这是在 Oracle 10g 上运行,大约需要 3 秒才能完成。考虑到它执行其他查询的速度,这似乎很极端。

编辑 表定义:
CREATE TABLE BAR
 (
    "BAR_ID" NUMBER NOT NULL,
    "QUADRANT" VARCHAR2(100 BYTE) NOT NULL,
    CONSTRAINT "BAR_PK" PRIMARY KEY ("BAR_ID")
 )

 CREATE TABLE FOO
 (  "FOO_ID" NUMBER NOT NULL, 
    "BAR_ID" NUMBER NOT NULL, 
    "NAME" VARCHAR2(250 BYTE) NOT NULL, 
    "DESCRIPTION" VARCHAR2(250 BYTE),
    CONSTRAINT "FOO_PK" PRIMARY KEY ("FOO_ID"), 
    CONSTRAINT "FOO__FK1" FOREIGN KEY ("BAR_ID") REFERENCES BAR ("BAR_ID") ENABLE
 );

最佳答案

你确定你有很好的统计数据吗?我从你的 DDL 创建了一个测试用例,并在统计之前看到了这个计划:

--------------------------------------------------------------------------- 
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     | 
--------------------------------------------------------------------------- 
|   0 | SELECT STATEMENT   |      |  4996 |  1619K|    10  (10)| 00:00:01 | 
|*  1 |  HASH JOIN         |      |  4996 |  1619K|    10  (10)| 00:00:01 | 
|   2 |   TABLE ACCESS FULL| BAR  |     5 |   325 |     3   (0)| 00:00:01 | 
|   3 |   TABLE ACCESS FULL| FOO  |  4996 |  1302K|     6   (0)| 00:00:01 | 
--------------------------------------------------------------------------- 

(如果您获得 dbms_xplan 输出,您还将看到“用于此语句的动态采样”)。

这样做之后:
SQL> begin dbms_stats.gather_table_stats(user,'FOO'); end;
  2  /

PL/SQL procedure successfully completed.

SQL> c/FOO/BAR/
  1* begin dbms_stats.gather_table_stats(user,'BAR'); end;
SQL> /

PL/SQL procedure successfully completed.

我懂了:
--------------------------------------------------------------------------------------- 
| Id  | Operation                    | Name   | Rows  | Bytes | Cost (%CPU)| Time     | 
--------------------------------------------------------------------------------------- 
|   0 | SELECT STATEMENT             |        |  4996 |   131K|     9  (12)| 00:00:01 | 
|   1 |  MERGE JOIN                  |        |  4996 |   131K|     9  (12)| 00:00:01 | 
|   2 |   TABLE ACCESS BY INDEX ROWID| BAR    |     5 |    40 |     2   (0)| 00:00:01 | 
|   3 |    INDEX FULL SCAN           | BAR_PK |     5 |       |     1   (0)| 00:00:01 | 
|*  4 |   SORT JOIN                  |        |  4996 | 94924 |     7  (15)| 00:00:01 | 
|   5 |    TABLE ACCESS FULL         | FOO    |  4996 | 94924 |     6   (0)| 00:00:01 | 
--------------------------------------------------------------------------------------- 

关于sql - 为什么这个查询这么慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3168941/

相关文章:

search - 如何配置 Solr 以对字段名称(而不是值)执行不区分大小写的搜索?

mysql - MySQL 表中的列是否有唯一且正常的索引?

sql - 将(非 CSV)文本数据导入 PostgreSQL,以空格和一个大写字母分隔

Eclipse - JBoss (Hibernate) 工具不显示任何表格

sql - 将列选择为按列值分组的行

sql - ORACLE-SQL : Function, 如何检测空选择并返回 0

sql - 如何声明变量并在同一个 Oracle SQL 脚本中使用它?

sql - 为什么 SQLite 不使用我的索引进行排序

java - Criteria API 中按目标加入

mysql - 更新表中的最小值