zoukankan      html  css  js  c++  java
  • [20191011]通过bash计算sql语句的sql_id.txt

    [20191011]通过bash计算sql语句的sql_id.txt

    --//当我知道如何通过bash计算sql语句的full_hash_value ,就很想通过bash编程计算sql_id.当时受限自己能力
    --//感觉不好实现.
    --//链接: http://blog.itpub.net/267265/viewspace-2142512/=> [20170724]关于sql_id那些事.txt

    1.简单介绍sql_id.
    --//sql_id的计算是使用MD5算法进行哈希,生成一个128位的Hash Value,其中低32位作为HASH VALUE显示,SQL_ID则取了后64位。
    --//实际上sql_id使用32进制表示,hash_value使用10进制表示。

    2.环境:
    SCOTT@book> @ &r/ver1
    PORT_STRING                    VERSION        BANNER
    ------------------------------ -------------- --------------------------------------------------------------------------------
    x86_64/Linux 2.4.xx            11.2.0.4.0     Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production

    select * from emp where deptno=10;
    --//查询可以知道sql_id='557p4j1ggw222'.

    SCOTT@book> select sql_text c70,sql_id,hash_value  from v$sql where sql_id = '557p4j1ggw222';
    C70                                SQL_ID        HASH_VALUE
    ---------------------------------- ------------- ----------
    select * from emp where deptno=10  557p4j1ggw222 1593706562

    SCOTT@book> select name c70,hash_value,full_hash_value from V$DB_OBJECT_CACHE where name like '%emp%' and hash_value=1593706562;
    C70                               HASH_VALUE FULL_HASH_VALUE
    --------------------------------- ---------- --------------------------------
    select * from emp where deptno=10 1593706562 8bb974871a4f8c88529ea4885efe0842
    select * from emp where deptno=10 1593706562 8bb974871a4f8c88529ea4885efe0842

    --//注以上是以前的测试!!

    3.简单说明如何计算sql_id:
    --//简单说明sql_id采用32进制,编码0-9,a-z.没有eilo字符,这些字符容易与数字0,1混淆.
    --//编程利用bc obase=32;ibase=16;输出.通过数组BASE32定位编码.注意bc的输出例子:
    $ echo "obase=32;ibase=16; 529EA4885EFE0842" | bc| tr -d '\ '
     05 05 07 21 04 17 01 15 15 28 02 02 02
    --//这些数字是10进制数字,前面虽然有0,不能写成${BASE32[$i]},必须写成{BASE32[$(( 10#$i ))]}.

    $ ./sql_id.sh "select * from emp where deptno=10"
    sql_text = select * from emp where deptno=10
    full_hash_value(16) = 8BB974871A4F8C88529EA4885EFE0842
    hash_value(10) = 1593706562
    sql_id = 557p4j1ggw222

    --//再测试一个例子:
    SCOTT@test01p> select /*+ 12345678abdef */ sysdate from dual ;
    SYSDATE
    -------------------
    2019-10-11 22:34:56

    SCOTT@test01p> @ dpc '' ''
    PLAN_TABLE_OUTPUT
    -------------------------------------
    SQL_ID  0p0rzks2gkrj6, child number 0
    -------------------------------------
    select /*+ 12345678abdef */ sysdate from dual

    Plan hash value: 1388734953

    ------------------------------------------------------------------
    | Id  | Operation        | Name | E-Rows | Cost (%CPU)| E-Time   |
    ------------------------------------------------------------------
    |   0 | SELECT STATEMENT |      |        |     2 (100)|          |
    |   1 |  FAST DUAL       |      |      1 |     2   (0)| 00:00:01 |
    ------------------------------------------------------------------
    --//sql_id=0p0rzks2gkrj6,主要要找一个sql_id前面是0的情况.注意dual后面有1个空格.

    $ ./sql_id.sh "select /*+ 12345678abdef */ sysdate from dual "
    sql_text = select /*+ 12345678abdef */ sysdate from dual
    full_hash_value(16) = EF5A2C4876C9E93D0A82FF9604F95E26
    hash_value(10) = 83451430
    sql_id(32) = 0p0rzks2gkrj6

    --//完成能对上.
    SCOTT@test01p> select name c70,hash_value,full_hash_value from V$DB_OBJECT_CACHE where  hash_value=83451430;
    C70                                           HASH_VALUE FULL_HASH_VALUE
    --------------------------------------------- ---------- --------------------------------
    select /*+ 12345678abdef */ sysdate from dual   83451430 ef5a2c4876c9e93d0a82ff9604f95e26
    select /*+ 12345678abdef */ sysdate from dual   83451430 ef5a2c4876c9e93d0a82ff9604f95e26


    4.总结:
    --//我几乎是一气呵成写成脚本,当我回过头看我写的脚本,感觉原来如此简单.
    --//自己真没想到短短几行代码,就能实现这个功能.

    5.脚本如下:
    $ cat sql_id.sh
    #! /bin/bash
    # calcucate sql_text of full_hash_value(16),hash_value(10),sql_id(32).
    odebug=${ODEBUG:-0}

    sql_text=${1}''
    v1=$(echo -e -n "$sql_text" | md5sum | sed 's/  -//' | xxd -r -p | od -t x4 |  sed   -n  -e 's/^0+ //' -e 's/ //gp' | tr 'a-z' 'A-Z')
    v2=${v1:(-16):16}
    v3=${v2:(-8):8}
    # v2=$(echo "obase=16;ibase=16; $v1 % 10000000000000000" | bc| tr -d '\ ')
    # v3=$(echo "obase=10;ibase=16; $v1 % 100000000" | bc| tr -d '\ ')

    if [ $odebug -eq 1 ] ; then
        echo v1=$v1 v2=$v2 v3=$v3
    fi

    echo "sql_text = $sql_text"
    echo "full_hash_value(16) = $v1 "
    echo "hash_value(10) = $(( 16#$v3 )) "

    BASE32=($(echo {0..9} {a..z} | tr -d 'eilo'))
    res=''
    for i in $(echo "obase=32;ibase=16; $v2" | bc| tr -d '\ ')
    do
        res=${res}${BASE32[$(( 10#$i ))]}
    done
    echo "sql_id(32) = $(printf "%13s" $res | tr ' ' '0')"

  • 相关阅读:
    蓝桥网试题 java 基础练习 特殊的数字
    蓝桥网试题 java 基础练习 杨辉三角形
    蓝桥网试题 java 基础练习 查找整数
    蓝桥网试题 java 基础练习 数列特征
    蓝桥网试题 java 基础练习 字母图形
    蓝桥网试题 java 基础练习 01字串
    蓝桥网试题 java 基础练习 回文数
    蓝桥网试题 java 基础练习 特殊回文数
    Using text search in Web page with Sikuli
    each of which 用法
  • 原文地址:https://www.cnblogs.com/lfree/p/11657506.html
Copyright © 2011-2022 走看看