in/exists和not in/not exists执行效率

一、IN 与EXISTS
1、理解
IN的执行流程
SELECT * FROM T1 WHERE X IN (SELECT Y FROM T2)
事实上可以理解为:
SELECT * FROM T1, (SELECT DISTINCT Y FROM T2) T2 WHERE T1.X = T2.Y
从这里可以看出,IN需要先处理T2表,然后再和T1进行关联

EXISTS的执行流程

SELECT * FROM T1 WHERE EXISTS (SELECT NULL FROM T2 WHERE Y = X)
--可以理解为:
for x in ( select * from t1 ) LOOP
    if ( exists ( select null from t2 where y = x.x )THEN 
        OUTPUT THE RECORD
    end if
end loop

从这里看出,EXISXTS会先查询T1表,然后再LOOP处理T2表

2、结论
对于in 和 exists的区别: 如果子查询得出的结果集记录较少,主查询中的表较大且又有索引时应该用in, 反之如果外层的主查询记录较少,子查询中的表大,又有索引时使用exists。其实我们区分in和exists主要是造成了驱动顺序的改变(这是性能变化的关键),如果是exists,那么以外层表为驱动表,先被访问,如果是IN,那么先执行子查询,所以我们会以驱动表的快速返回为目标,那么就会考虑到索 引及结果集的关系了。
综合以上对IN/EXISTS的讨论,我们可以得出一个基本通用的结论:IN适合于外表大而内表小的情况;EXISTS适合于外表小而内表大的情况。

二、NOT IN 与NOT EXISTS
1、理解
NOT IN的执行流程
SELECT * FROM T1 WHERE X NOT IN (SELECT Y FROM T2)
事实上可以理解为:
SELECT * FROM T1, (SELECT DISTINCT Y FROM T2) T2 WHERE T1.X != T2.Y

NOT EXISTS的执行流程

SELECT .. .. .
  FROM ROLLUP R
 WHERE NOT EXISTS
 (SELECT 'Found' FROM TITLE T WHERE R.SOURCE_ID = T.TITLE_ID);
--可以理解为:
for x in ( select * from rollup )
       loop
           if ( not exists ( that query ) ) then
                  OUTPUT
           end if;
        end;

注意:NOT EXISTS 与 NOT IN 不能完全互相替换,看具体的需求。如果选择的列可以为空,则不能被替换。具体见:in/exists和not in/not exists语意探讨

2、结论
not in 只有当子查询中,select 关键字后的字段有not null约束或者有这种暗示时用not in,另外如果主查询中表大,子查询中的表小但是记录多,则应当使用not in,并使用anti hash join.如果主查询表中记录少,子查询表中记录多,并有索引,可以使用not exists,另外not in最好也可以用/*+ HASH_AJ */或者外连接+is null.一般情况下建议使用not exists

--比如:
SELECT .. .. ..
  FROM ROLLUP R
 WHERE NOT EXISTS
 (SELECT 'Found' FROM TITLE T WHERE R.SOURCE_ID = T.TITLE_ID);
--改成
SELECT .. .. ..
  FROM TITLE T, ROLLUP R
 WHERE R.SOURCE_ID = T.TITLE_ID(+)
   AND T.TITLE_ID IS NULL;
--或者
SELECT /*+ HASH_AJ */
.. .. ..
  FROM ROLLUP R
 WHERE OURCE_ID NOT IN
       (SELECT OURCE_ID FROM TITLE T WHERE OURCE_ID IS NOT NULL);
发表在 Oracle 开发 | 2 条评论

hosts中缺少localhost.localdomain导致监听启动时间超长

0、基本信息

[oracle@localhost ~]$ uname -a
Linux localhost.localdomain 2.6.18-194.el5PAE #1 SMP Tue Mar 16 22:00:21 EDT 2010 i686 i686 i386 GNU/Linux
[oracle@localhost ~]$ hostname
localhost.localdomain
[oracle@localhost ~]$ /sbin/ifconfig 
eth0      Link encap:Ethernet  HWaddr 00:14:22:10:96:AE  
          inet addr:192.168.9.66  Bcast:192.168.11.255  Mask:255.255.252.0
          inet6 addr: fe80::214:22ff:fe10:96ae/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:6597875 errors:0 dropped:0 overruns:0 frame:0
          TX packets:9785915 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100 
          RX bytes:2526369384 (2.3 GiB)  TX bytes:295978844 (282.2 MiB)

eth0:1    Link encap:Ethernet  HWaddr 00:14:22:10:96:AE  
          inet addr:外网ip  Bcast:211.155.227.175  Mask:255.255.255.240
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1

eth1      Link encap:Ethernet  HWaddr 00:14:22:10:96:AF  
          inet addr:192.168.11.50  Bcast:192.168.11.255  Mask:255.255.252.0
          inet6 addr: fe80::214:22ff:fe10:96af/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:999903 errors:0 dropped:0 overruns:0 frame:0
          TX packets:283 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100 
          RX bytes:104688608 (99.8 MiB)  TX bytes:22777 (22.2 KiB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:8816738 errors:0 dropped:0 overruns:0 frame:0
          TX packets:8816738 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:2726275798 (2.5 GiB)  TX bytes:2726275798 (2.5 GiB)
[oracle@localhost ~]$ more /etc/sysconfig/network
NETWORKING=yes
NETWORKING_IPV6=yes
HOSTNAME=localhost.localdomain

1、hosts文件

[oracle@localhost ~]$ more /etc/hosts
127.0.0.1                 localhost

2、监听文件

[oracle@localhost ~]$ more /opt/oracle/product/10g/network/admin/listener.ora
# listener.ora Network Configuration File: /opt/oracle/product/10g/network/admin/listener.ora
# Generated by Oracle configuration tools.

SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (GLOBAL_DBNAME = gaxt)
      (ORACLE_HOME = /opt/oracle/product/10g)
      (SID_NAME = gaxt)
    )
  )

LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 外网IP)(PORT = 1521)) 
      (ADDRESS = (PROTOCOL = TCP)(HOST = 127.0.0.1)(PORT = 1521))
    )
  )

3、启动监听

[oracle@localhost ~]$ lsnrctl start

LSNRCTL for Linux: Version 10.2.0.4.0 - Production on 15-DEC-2011 23:27:32

Copyright (c) 1991, 2007, Oracle.  All rights reserved.

Starting /opt/oracle/product/10g/bin/tnslsnr: please wait...

TNSLSNR for Linux: Version 10.2.0.4.0 - Production
System parameter file is /opt/oracle/product/10g/network/admin/listener.ora
Log messages written to /opt/oracle/product/10g/network/log/listener.log
Trace information written to /tmp/listener_trc.trc
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=外网IP)(PORT=1521)))
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=127.0.0.1)(PORT=1521)))

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=外网IP)(PORT=1521)))
--这里卡了很久很久才显示成功
STATUS of the LISTENER
------------------------
Alias                     LISTENER
Version                   TNSLSNR for Linux: Version 10.2.0.4.0 - Production
Start Date                15-DEC-2011 23:27:32
Uptime                    0 days 0 hr. 3 min. 9 sec
Trace Level               support
Security                  ON: Local OS Authentication
SNMP                      OFF
Listener Parameter File   /opt/oracle/product/10g/network/admin/listener.ora
Listener Log File         /opt/oracle/product/10g/network/log/listener.log
Listener Trace File       /tmp/listener_trc.trc
Listening Endpoints Summary...
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=外网IP)(PORT=1521)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=127.0.0.1)(PORT=1521)))
Services Summary...
Service "gaxt" has 1 instance(s).
  Instance "gaxt", status UNKNOWN, has 1 handler(s) for this service...
The command completed successfully

4、开启监听trace

--在/opt/oracle/product/10g/network/admin/listener.ora中加入下列参数
TRACE_LEVEL_LISTENER = 16
TRACE_FILE_LISTENER= LISTENER_TRC
TRACE_DIRECTORY_LISTENER=/tmp

6、重启监听查看trace文件

[15-DEC-2011 23:33:32:938] --- TRACE CONFIGURATION INFORMATION FOLLOWS ---
[15-DEC-2011 23:33:32:938] New trace stream is /tmp/listener_trc.trc
[15-DEC-2011 23:33:32:938] New trace level is 16
…………………………
[15-DEC-2011 23:33:32:981] nsnainconn: no native services in use - returning
[15-DEC-2011 23:33:32:981] nsnainconn: signalling that calling function should not continue
[15-DEC-2011 23:33:32:982] nsnainconn: normal exit
[15-DEC-2011 23:33:32:982] nsnaconn: normal exit
[15-DEC-2011 23:33:32:982] nsaccept: exit (0)
[15-DEC-2011 23:36:41:965] nsglma: WARNING - SNMP master agent is not running OR snmp.ora file does not exist.
[15-DEC-2011 23:36:41:965] nsevwait: entry
[15-DEC-2011 23:36:41:965] nsevwait: 3 registered connection(s)
[15-DEC-2011 23:36:41:965] nsevwait: 0 pre-posted event(s)
[15-DEC-2011 23:36:41:965] nsevwait: waiting for transport event (1 thru 4)...
[15-DEC-2011 23:36:41:965] nsevwait: 1 newly-posted event(s)

这里可以看出监听启动的过程中,在这个地方等待了3分钟之久
MOS:Lsnrctl Start is Extremely Slow or Appears to Hang

7、修改hosts文件

[oracle@localhost ~]$ more /etc/hosts
127.0.0.1               localhost.localdomain localhost

8、重启监听查看trace文件

[15-DEC-2011 23:43:44:555] --- TRACE CONFIGURATION INFORMATION FOLLOWS ---
[15-DEC-2011 23:43:44:555] New trace stream is /tmp/listener_trc.trc
……………………
[15-DEC-2011 23:43:44:627] nsevwait: entry
[15-DEC-2011 23:43:44:627] nsevwait: 3 registered connection(s)
[15-DEC-2011 23:43:44:627] nsevwait: 0 pre-posted event(s)
[15-DEC-2011 23:43:44:627] nsevwait: waiting for transport event (1 thru 4)...

这里可以看出监听启动一共使用时间为:几十毫秒

9、结论
在主机名为localhost.localdomain的hosts文件中缺少127.0.0.1 localhost.localdomain,哪怕监听中配置的是ip地址,也将导致监听启动时间非常长。如果主机名不是localhost.localdomain,那hosts中缺少localhost.localdomain没有影响监听启动。

发表在 Oracle 监听 | 评论关闭

hostname配置不切当导致TNS-12542错误

一、监听异常现象

[oracle@gongantest ~]$ lsnrctl start

LSNRCTL for Linux: Version 10.2.0.4.0 - Production on 15-DEC-2011 14:15:06

Copyright (c) 1991, 2007, Oracle.  All rights reserved.

Starting /opt/oracle/product/10.2.0/db_1/bin/tnslsnr: please wait...

TNSLSNR for Linux: Version 10.2.0.4.0 - Production
System parameter file is /opt/oracle/product/10.2.0/db_1/network/admin/listener.ora
Log messages written to /opt/oracle/product/10.2.0/db_1/network/log/listener.log
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=gongantest)(PORT=1521)))
Error listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.11.60)(PORT=1521)))
TNS-12542: TNS:address already in use
 TNS-12560: TNS:protocol adapter error
  TNS-00512: Address already in use
   Linux Error: 98: Address already in use

Listener failed to start. See the error message(s) above...


[oracle@gongantest ~]$ more /opt/oracle/product/10.2.0/db_1/network/admin/listener.ora
# listener.ora Network Configuration File: /opt/oracle/product/10.2.0/db_1/network/admin/listener.ora
# Generated by Oracle configuration tools.

SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (SID_NAME = PLSExtProc)
      (ORACLE_HOME = /opt/oracle/product/10.2.0/db_1)
      (PROGRAM = extproc)
    )
  )

LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCP)(HOST = gongantest)(PORT = 1521))
      (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.11.60)(PORT = 1521))
    )
  )

二、相关网络配置

[oracle@gongantest ~]$ ping gongantest -c 2
PING gongantest (127.0.0.1) 56(84) bytes of data.
64 bytes from gongantest (127.0.0.1): icmp_seq=1 ttl=64 time=0.040 ms
64 bytes from gongantest (127.0.0.1): icmp_seq=2 ttl=64 time=0.016 ms

--- gongantest ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.016/0.028/0.040/0.012 ms


[oracle@gongantest ~]$ more /etc/hosts
# Do not remove the following line, or various programs
# that require network functionality will fail.
127.0.0.1               gongantest localhost.localdomain localhost

[oracle@gongantest ~]$ cd /etc/sysconfig/network-scripts
[oracle@gongantest network-scripts]$ more ifcfg-eth0 
# Intel Corporation 82541GI Gigabit Ethernet Controller
DEVICE=eth0
BOOTPROTO=static
BROADCAST=192.168.11.255
HWADDR=00:14:22:10:96:C9
IPADDR=192.168.11.60
NETMASK=255.255.252.0
NETWORK=192.168.8.0
ONBOOT=yes
[oracle@gongantest network-scripts]$ more ifcfg-eth1
# Intel Corporation 82541GI Gigabit Ethernet Controller
DEVICE=eth1
BOOTPROTO=dhcp
HWADDR=00:14:22:10:96:CA
ONBOOT=no
HOTPLUG=no
DHCP_HOSTNAME=gongantest
[oracle@gongantest network-scripts]$ hostname
gongantest
[oracle@gongantest network-scripts]$ more /etc/sysconfig/network
NETWORKING=yes
NETWORKING_IPV6=no
HOSTNAME=gongantest
GATEWAY=192.168.8.1

三、解决问题

[oracle@gongantest ~]$ more /opt/oracle/product/10.2.0/db_1/network/admin/listener.ora
# listener.ora Network Configuration File: /opt/oracle/product/10.2.0/db_1/network/admin/listener.ora
# Generated by Oracle configuration tools.

SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (SID_NAME = PLSExtProc)
      (ORACLE_HOME = /opt/oracle/product/10.2.0/db_1)
      (PROGRAM = extproc)
    )
  )

LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 127.0.0.1)(PORT = 1521))
      (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.11.60)(PORT = 1521))
    )
  )



[oracle@gongantest etc]$ lsnrctl start

LSNRCTL for Linux: Version 10.2.0.4.0 - Production on 15-DEC-2011 14:17:54

Copyright (c) 1991, 2007, Oracle.  All rights reserved.

Starting /opt/oracle/product/10.2.0/db_1/bin/tnslsnr: please wait...

TNSLSNR for Linux: Version 10.2.0.4.0 - Production
System parameter file is /opt/oracle/product/10.2.0/db_1/network/admin/listener.ora
Log messages written to /opt/oracle/product/10.2.0/db_1/network/log/listener.log
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=127.0.0.1)(PORT=1521)))
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.11.60)(PORT=1521)))

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521)))
STATUS of the LISTENER
------------------------
Alias                     LISTENER
Version                   TNSLSNR for Linux: Version 10.2.0.4.0 - Production
Start Date                15-DEC-2011 14:17:54
Uptime                    0 days 0 hr. 0 min. 0 sec
Trace Level               off
Security                  ON: Local OS Authentication
SNMP                      OFF
Listener Parameter File   /opt/oracle/product/10.2.0/db_1/network/admin/listener.ora
Listener Log File         /opt/oracle/product/10.2.0/db_1/network/log/listener.log
Listening Endpoints Summary...
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=127.0.0.1)(PORT=1521)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.11.60)(PORT=1521)))
Services Summary...
Service "PLSExtProc" has 1 instance(s).
  Instance "PLSExtProc", status UNKNOWN, has 1 handler(s) for this service...
The command completed successfully

四、补充说明
如果把hostname配置在hosts中的127.0.0.1项,那么如果在监听中使用了hostname,再配置一个host监听该机器的ip地址(非127.0.0.1),那么会报文章开头的错误,解决方法有两种:
1、监听中全部采用ip地址
2、在hosts中配置hostname对应ip地址(非127.0.0.1)

发表在 Oracle 监听 | 一条评论