• [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')"

  • 相关阅读:
    PHPUnit断言详情
    dev tools杂谈
    sublime text3 + python3.5 ide
    文件传输接收sz、rz命令用法
    Linux编辑器vi使用方法详细介绍
    vi编辑字符串替换及sed用法
    Selenium实战(一)——浏览器实例
    Python的数据库连接
    Cypress测试框架——一个简单的测试用例
    Cypress测试框架——入门1
  • 原文地址:https://www.cnblogs.com/lfree/p/11657506.html
Copyright © 2020-2023  润新知