前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Oracle 和 Mysql 的索引在Null字段上处理的异同

Oracle 和 Mysql 的索引在Null字段上处理的异同

作者头像
SQLplusDB
发布2022-08-22 13:36:24
9890
发布2022-08-22 13:36:24
举报

编者按:

本文作者系Scott(中文名陈晓辉),ORACLE数据库专家,就职于甲骨文中国。个人主页:segmentfault.com/u/db_perf ,经其本人授权发布。

【免责声明】本号文章仅代表个人观点,与任何公司无关。

编辑|SQL和数据库技术(ID:SQLplusDB)

ORACLE:

代码语言:javascript
复制
SQL> create table tab2(c1 number, c2 number, c3 varchar2(10));

表が作成されました。

SQL> declare
  a number;
begin
  a := 1;
  for i in 1 .. 500 loop
    for j in 1 .. 1000 loop
      insert into tab2 values(a,j,'a');
      commit;
      a := a+1;
    end loop;
  end loop;
end;
/

PL/SQLプロシージャが正常に完了しました。

SQL> create index ind2_2 on tab2(c2);

索引が作成されました。

SQL> insert into tab2 values(9999,null,'test');

1行が作成されました。

SQL> commit;

コミットが完了しました。

SQL> exec dbms_stats.gather_table_stats(ownname=>'TEST',tabname=>'TAB2',cascade=>TRUE);

PL/SQLプロシージャが正常に完了しました。

SQL> set lin 150 pages 9999
SQL> set autot traceonly exp
SQL> select count(*) from tab2 where c2 is null;

実行計画
----------------------------------------------------------
Plan hash value: 2781695375

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 |     4 |   310   (1)| 00:00:01 |
|   1 |  SORT AGGREGATE    |      |     1 |     4 |            |          |
|*  2 |   TABLE ACCESS FULL| TAB2 |     1 |     4 |   310   (1)| 00:00:01 |
---------------------------------------------------------------------------

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

   2 - filter("C2" IS NULL)

SQL> select count(*) from tab2 where c2=10;

実行計画
----------------------------------------------------------
Plan hash value: 3563712581

----------------------------------------------------------------------------
| Id  | Operation         | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |        |     1 |     4 |     4   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE   |        |     1 |     4 |            |          |
|*  2 |   INDEX RANGE SCAN| IND2_2 |   500 |  2000 |     4   (0)| 00:00:01 |
----------------------------------------------------------------------------

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

   2 - access("C2"=10)

Mysql(Innodb):

代码语言:javascript
复制
mysql> create table tab2(c1 int, c2 int, c3 varchar(10));
Query OK, 0 rows affected (0.01 sec)

mysql> delimiter //
mysql> create procedure my_procedure()
-> begin
-> DECLARE n int DEFAULT 1;
-> WHILE n < 1001 DO
-> insert into tab2(c1,c2,c3) value (n,n,'desc');
-> set n = n + 1;
-> END WHILE;
-> end
-> //
Query OK, 0 rows affected (0.01 sec)

mysql> delimiter ;
mysql> call my_procedure;
Query OK, 1 row affected (0.84 sec)

mysql> create index ind2_2 on tab2(c2);
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> insert into tab2 values(9999,null,'test');
Query OK, 1 row affected (0.00 sec)

mysql> explain select count(*) from tab2 where c2=10;
+----+-------------+-------+------------+------+---------------+--------+---------+-------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key    | key_len | ref   | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+--------+---------+-------+------+----------+-------------+
|  1 | SIMPLE      | tab2  | NULL       | ref  | ind2_2        | ind2_2 | 5       | const |    1 |   100.00 | Using index |
+----+-------------+-------+------------+------+---------------+--------+---------+-------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

mysql> explain select count(*) from tab2 where c2 is null;
+----+-------------+-------+------------+------+---------------+--------+---------+-------+------+----------+--------------------------+
| id | select_type | table | partitions | type | possible_keys | key    | key_len | ref   | rows | filtered | Extra                    |
+----+-------------+-------+------------+------+---------------+--------+---------+-------+------+----------+--------------------------+
|  1 | SIMPLE      | tab2  | NULL       | ref  | ind2_2        | ind2_2 | 5       | const |    1 |   100.00 | Using where; Using index |
+----+-------------+-------+------------+------+---------------+--------+---------+-------+------+----------+--------------------------+
1 row in set, 1 warning (0.00 sec)

结论:

Oracle的B-tree索引不存储Null,所以“c2 is null”条件的检索不能从索引中受益。 Mysql的B+tree索引也不直接不存储Null,但是“c2 is null”条件的检索能从索引中受益。

https://dev.mysql.com/doc/refman/8.0/en/is-null-optimization.html

ref_or_null works by first doing a read on the reference key, and then a separate search for rows with a NULL key value.

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-01-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 SQL和数据库技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档