[20181130]如何猜測那些值存在hash衝突.txt

来源:https://www.cnblogs.com/lfree/archive/2018/11/30/10043032.html
-Advertisement-
Play Games

[20181130]如何猜測那些值存在hash衝突.txt--//今年6月份開始kerrycode的1個帖子提到子查詢結果緩存在哈希表中情況:--//鏈接:http://www.cnblogs.com/kerrycode/p/9099507.html,摘要:通俗來將,當使用標量子查詢的時候,ORAC ...


[20181130]如何猜測那些值存在hash衝突.txt

--//今年6月份開始kerrycode的1個帖子提到子查詢結果緩存在哈希表中情況:
--//鏈接:http://www.cnblogs.com/kerrycode/p/9099507.html,摘要:
通俗來將,當使用標量子查詢的時候,ORACLE會將子查詢結果緩存在哈希表中, 如果後續的記錄出現同樣的值,優化器通過緩存在哈希
表中的值,判斷重覆值不用重覆調用函數,直接使用上次計算結果即可。從而減少調用函數次數,從而達到優化性能的效果。另外在
ORACLE 10和11中, 哈希表只包含了255個Buckets,也就是說它能存儲255個不同值,如果超過這個範圍,就會出現散列衝突,那些出現
散列衝突的值就會重覆調用函數,即便如此,依然能達到大幅改善性能的效果。

--//我當時就非常想從作者瞭解"哈希表只包含了255個Buckets",這個觀點的出處.kerrycode給了我一個鏈接:
https://blogs.oracle.com/oraclemagazine/on-caching-and-evangelizing-sql

Oracle Database will use this hash table to remember the scalar subquery and the inputs to it—just :DEPTNO in this case
—and the output from it. At the beginning of every query execution, this cache is empty, but suppose you run the query
and the first PROJECTS row you retrieve has a DEPTNO value of 10. Oracle Database will assign the number 10 to a hash
value between 1 and 255 (the size of the hash table cache in Oracle Database 10g and Oracle Database 11g currently) and
will look in that hash table slot to see if the answer exists. In this case, it will not, so Oracle Database must run
the scalar subquery with the input of 10 to get the answer. If that answer (count) is 42, the hash table may look
something like this:

Select count(*) from emp where emp.deptno = :deptno
:deptno     Count(*)

You'll have saved the DEPTNO value of 10 and the answer (count) of 42 in some slot—probably not the first or last slot,
but whatever slot the hash value 10 is assigned to. Now suppose the second row you get back from the PROJECTS table
includes a DEPTNO value of 20. Oracle Database will again look in the hash table after assigning the value 20, and it
will discover "no result in the cache yet." So it will run the scalar subquery, get the result, and put it into the hash
table cache. Now the cache may look like this:

Select count(*) from emp where emp.deptno = :deptno
:deptno     Count(*)
Select count(*) from emp where emp.deptno = :deptno
:deptno     Count(*)
…     …
10     42

Now suppose the query returns a third row and it again includes a DEPTNO value of 10. This time, Oracle Database will
see DEPTNO = 10, find that it already has that value in the hash table cache, and will simply return 42 from the cache
instead of executing the scalar subquery. In fact, it will never have to run that scalar subquery for the DEPTNO values
of 10 or 20 again for that query—it will already have the answer.

What happens if the number of unique DEPTNO values exceeds the size of the hash table? What if there are more than 255
values? Or, more generally, if more than one DEPTNO value is assigned to the same slot in the hash table, what happens
in a hash collision?

The answer is the same for all these questions and is rather simple: Oracle Database will not be able to cache the
second or nth value to that slot in the hash table. For example, what if the third row returned by the query contains
the DEPTNO = 30 value? Further, suppose that DEPTNO = 30 is to be assigned to exactly the same hash table slot as DEPTNO
= 10. The database won't be able to effectively cache DEPTNO = 30 in this case—the value will never make it into the
hash table. It will, however, be "partially cached." Oracle Database still has the hash table with all the previous
executions, but it also keeps the last scalar subquery result it had "next to" the hash table. That is, if the fourth
row also includes a DEPTNO = 30 value, Oracle Database will discover that the result is not in the hash table but is
"next to" the hash table, because the last time it ran the scalar subquery, it was run with an input of 30. On the other
hand, if the fourth row includes a DEPTNO = 40 value, Oracle Database will run the scalar subquery with the DEPTNO = 40
value (because it hasn't seen that value yet during this query execution) and overwrite the DEPTNO = 30 result. The next
time Oracle Database sees DEPTNO = 30 in the result set, it'll have to run that scalar subquery again.

--//我自己開始瞎嘗試各種方法驗證hash buckets是否是255.我開始先入為主,認為就是255(或者256),經歷許多混亂,最後kerrycode給我
--//一個測試方法,鏈接如下:
http://blog.itpub.net/267265/viewspace-2156702/
http://www.cnblogs.com/kerrycode/p/9223093.html

--//按照這個方法很容易驗證hash buckets大小,11.2.0.4是1024,10.2.0.4是512,12.1.0.1是1024.
--//我想起開始測試時,75與48存在衝突的情況,當時我沒有想到這麼靠前的值存在衝突,為了驗證我幾乎是1個1個嘗試.
--//因為你根本不知道oracle的演算法.
--//昨天看https://jonathanlewis.wordpress.com/2018/11/26/shrink-space-2/,驗證為什麼4與432存在衝突.

1.環境:
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

create or replace function f( x in varchar2 ) return number
as
begin
        dbms_application_info.set_client_info(userenv('client_info')+1 );
        return length(x);
end;
/

SCOTT@book> create table t as select rownum id1,mod(rownum-1,10000)+1 id2 from dual connect by level<=20000;
Table created.

SCOTT@book> create table t1 ( a number ,b number);
Table created.
--//欄位a 記錄調用函數次數.


2.建立測試腳本:
--//建立腳本cz.txt
exec dbms_application_info.set_client_info(0);
set term off
exec :x := &&1;
select count(distinct f_id2) from (select id2,(select f(id2) from dual) as f_id2 from t where id2 in (&&2,:x ));
set term on
insert into t1 values (userenv('client_info') ,:x) ;
commit ;

--//建立shell腳本cz.sh:
#! /bin/bash
sqlplus -s -l scott/book <<EOF >> hz.txt
variable x number;
$(seq 500 | xargs -I{} echo @cz.txt {} $1)
quit
EOF

3.測試:
--//執行腳本cz.sh:
$ . cz.sh 4

SCOTT@book> select * from t1 where a<>2;
         A          B
---------- ----------
         1          4
         3        432
--//可以發現4,432存在衝突.函數調用了3次.

SCOTT@book> delete t1;
500 rows deleted.

SCOTT@book> commit ;
Commit complete.

--//驗證1與那個值存在衝突.

$ . cz.sh 1

SCOTT@book> select * from t1 where a<>2;
         A          B
---------- ----------
         3        484
         1          1

--//可以驗證1與484存在hash衝突.

4.再拿鏈接例子做測試:
--//鏈接:https://jonathanlewis.wordpress.com/2018/11/26/shrink-space-2/
SCOTT@book> update emp set dept_no=484 where dept_no=432;
1 row updated.

SCOTT@book> commit ;
Commit complete.

SCOTT@book> alter session set statistics_level = all;
Session altered.

select
        /*+ gather_plan_statistics post-shrink  */
        count(*)
from    (
        select  /*+ no_merge */
                outer.*
        from emp outer
        where outer.sal >
                (
                        select /*+ no_unnest */ avg(inner.sal)
                        from emp inner
                        where inner.dept_no = outer.dept_no
                )
        )
;

  COUNT(*)
----------
      9498

SCOTT@book> @ dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  gx7xb7rhfd2zf, child number 0
-------------------------------------
select         /*+ gather_plan_statistics post-shrink  */
count(*) from    (         select  /*+ no_merge */
outer.*         from emp outer         where outer.sal >
 (                         select /*+ no_unnest */ avg(inner.sal)
                  from emp inner                         where
inner.dept_no = outer.dept_no                 )         )

Plan hash value: 322796046

------------------------------------------------------------------------------------------------------------------------
| Id  | Operation             | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |
------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |      |      1 |        |       |   569 (100)|          |      1 |00:00:03.43 |     783K|
|   1 |  SORT AGGREGATE       |      |      1 |      1 |       |            |          |      1 |00:00:03.43 |     783K|
|   2 |   VIEW                |      |      1 |    143 |       |   569   (1)| 00:00:07 |   9498 |00:00:03.42 |     783K|
|*  3 |    FILTER             |      |      1 |        |       |            |          |   9498 |00:00:03.42 |     783K|
|   4 |     TABLE ACCESS FULL | EMP  |      1 |  20001 |   156K|    71   (0)| 00:00:01 |  19001 |00:00:00.01 |     247 |
|   5 |     SORT AGGREGATE    |      |   3173 |      1 |     8 |            |          |   3173 |00:00:03.41 |     783K|
|*  6 |      TABLE ACCESS FULL| EMP  |   3173 |   2857 | 22856 |    71   (0)| 00:00:01 |     10M|00:00:02.71 |     783K|
------------------------------------------------------------------------------------------------------------------------
--//迴圈3173.

SCOTT@book> select dept_no,count(*) from emp group by dept_no order by 1;
   DEPT_NO   COUNT(*)
---------- ----------
         0       3167
         1       3167
         2       3167
         3       3166
         4       3166
         5       3167
       484          1
7 rows selected.
--//dept_no=1出現hash衝突.
--//dept_no=484 迴圈1次
--//dept_no=0   迴圈1次
--//dept_no=1   迴圈3167次
--//dept_no=2   迴圈1次
--//dept_no=3   迴圈1次
--//dept_no=4   迴圈1次
--//dept_no=5   迴圈1次

--//這樣累加: 1+1+3167+1+1+1+1 = 3173,這樣就相互驗證了.

4.我上面的測試純粹是蠻力測試,改寫為PL/SQL腳本看看,PL/sql確實不熟練....

SCOTT@book> create table t2 ( a number ,b number,c number);
Table created.
--//欄位a 記錄調用函數次數.

--//腳本cy.txt
declare
x number;
  begin
   for i in 1..10000 loop
     dbms_application_info.set_client_info(0);
     select count(distinct f_id2) into x from (select id2,(select f(id2) from dual) as f_id2 from t where id2 in (i, &&1 ) );
     if ( userenv('client_info') =3 ) then  
          insert into t2 values (userenv('client_info') ,i,&&1) ;
          commit ;
          exit;
     END IF;
   end loop;
end;
/
--//我加入發現後exit(退出).你可以註解或者取消,這樣測試1..10000之間的hash buckets衝突值.

--//執行如下:
@ cy.txt 4
@ cy.txt 1
@ cy.txt 3
@ cy.txt 18
@ cy.txt 48
@ cy.txt 75

SCOTT@book> select * from t2;
         A          B          C
---------- ---------- ----------
         3        432          4
         3        484          1
         3        735          3
         3       2071         18
         3         75         48
         3         48         75
6 rows selected.

--//這樣就很快知道那些值會發生hash衝突了.
--//不知道那位還有什麼更好的方法...


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 導入單個AD用戶命令 New-ADUser -Name "周八" -Surname "周" -GivenName "八"-SamAccountName "20160219008" -UserPrincipalName "[email protected]" -DisplayName "周八" -D ...
  • 一. 好用便利的工具,常用 pt-align 對齊文本格式pt-archiver 循序漸進的歸檔表,刪除表,遷移數據pt-config-diff 對比不同配置文件、伺服器配置參數pt-diskstats 查看磁碟iopt-fifo-split 把大文件通過管道分割成若幹小文件pt-kill 批量殺連 ...
  • 問題:Oracle EBS 11無法打開Form及Form顯示亂碼 解決: 1、嘗試使用jre1.5或1.6安裝目錄下jre/bin/server目錄里的jvm.dll替換JInitiator安裝目錄里的bin/hotspot目錄下的jvm.dll文件,如果替換後,後續操作提示錯誤,不妨再換為預設的 ...
  • 以前記錄數據可能很少也很簡單,比如說老王借了老李半斤肉,這樣的數據老李直接就寫到牆上就行了。 後來數據多了人們就以表格的方式開始記錄,寫到一張A4紙上,比如學生的檔案,有表頭和序號等。 表頭裡有姓名、性別、年齡、籍貫等等,有橫向的信息有豎向的信息。這樣的A4紙散放在那裡肯定是不行的。 於是人們把它們 ...
  • oracle11g中沒有scott用戶的解決,通過創建scott.sql文件,然後授予許可權,解鎖,修改密碼等一系列的操作來完成賬號建立 ...
  • 一.概述 除了上篇介紹的RDB持久化功能之外,Redis還提供了AOF(Append Only File)持久化功能。與RDB保存資料庫中的鍵值對來記錄資料庫狀態不同,AOF是通過保存redis伺服器所執行的寫命令來記錄資料庫狀態的。AOF持久化方式記錄每次對伺服器寫的操作,當伺服器啟動時,就會通過 ...
  • 摘要:當前研發工作中經常出現因資料庫表、資料庫表欄位格式不規則而影響開發進度的問題,在後續開發使用原來資料庫表時,也會因為資料庫表的可讀性不夠高,表欄位規則不統一,造成數據查詢,數據使用效率低的問題,所以有必要整理出一套合適的資料庫表欄位命名規範來解決優化這些問題。 本文是一篇包含了資料庫命名、數據 ...
  • mysql是一種關係型資料庫管理系統。以mysql5.7版本為例,安裝過程如下: 首先百度出mysql的官網,進入:(以下是自己安裝失敗的過程,直接下拉最後看大佬的安裝過程吧,就是那個紅紅的網址) 找到mysql的下載社區,找到對應的版本,這裡以mysql5.7為例: 這裡我們選擇zip格式安裝,對 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...