oracle開發 ip庫取資料的執行計畫問題

2021-06-22 04:33:04 字數 1963 閱讀 5843

**訪問日誌都會存在個基本問題,就是根據訪問者ip從ip庫中獲取ip所在國家(貌似有點繞口),它的使用場景比較廣泛,如現在的大部分**都可以通過來訪者的地域推送不同的內容。我們資料倉儲中,則要通過這個來分析**的國家訪問情況。

廢話不多說,上表

session_temp表是我建立的臨時表,從本站某天的真實訪問資料中把使用者的訪問ip全部導過來。本站一天的訪問資料在30000左右

ip_temp表是本站購買的ip庫,主要由三個字段構成

startip、endip指的是該ip段範圍

countryname指的是該ip段所對應的國家

示例值見下圖

比如對於1944892794這個ip,我們獲取它的國家執行如下:

這種查詢單個ip國家的語句一般是使用者訪問的時候做判斷,再根據他的國家做推算。這語句執行了7秒多,意思是使用者來訪問時,要至少7秒時間才能把頁面展示出來,肯定是不能接受的。

我們資料倉儲是對當天全部資料做查詢,則完全無法執行出結果。這樣的速度顯然是不能滿足生產環境的要求的。如下:

8分多鐘還沒出結果,即使資料倉儲中也無法忍受這種速度

**那邊說用mongodb可以解決問題,我還沒試過,估計也不大好整合其他種類資料庫的etl進來。所以還是要從執行計畫入手。先看下這句**的執行計畫

這個執行計畫有點難懂。oracle

先對session_temp做了全表掃瞄排序,因為只有2萬多行,所以應該是記憶體排序,問題不大。然後對根據startip<=ip這個條件,對t2表做了過濾,再全表掃瞄進行排序,400萬條資料排序,估計要用到磁碟了。兩張表排完後開始進行merge連線,連線條件是endip>=ip.

這個執行計畫看著就有點不靠譜,謂語的兩句地位相等,應該都用來做連線條件,結果oracle一句變成了條件過濾語句。endip>=ip這個條件並不是等式連線,如果用merge,意味著從session裡取出一條ip資料,需要在ip庫里把大於這個ip全部掃瞄一遍,效能是o(session+ip_temp*session)+o(sessionlog)+o(ip_templog)(oracle的排序演算法好像是nlogn,記憶體排)(難怪能跑出rows30g的資料), 而merge前的排序本身就是為了減少反覆的全表掃瞄,等於耗了大量精力的排序全部白幹。

既然merge也要兩邊都全表掃瞄,還不如用nest loop,session表遠小於ip庫表,所以它是驅動表。根據這個思路我們加上hints

select /*+leading(t1) use_nl(t1 t2)*/ * from session_temp t1,ip_temp t2 where t2.startip<=t1.ip and t2.endip>=t1.ip

檢視執行計畫

看上去合理了一點,不過各項指標貌似沒有明顯的改善,原因就不知道了。有時候cbo是有點傻,算出來的指標不一定對(暫時這麼解釋吧)。

看看效果:

執行時間還是不能滿足要求。

仔細想想,nest loop會反覆掃瞄外表,如果上面建個索引,每次都index range scan,顯然會快很多。所以在session上建立索引:

執行計畫似乎沒變,還是對兩張表都進行全表掃瞄。

不過後來發現時我理解錯了,谷歌了下hints leading的含義,它表示的是先載入t1表,每次一條資料,再去迴圈掃瞄t2表。那不就意味著t2表是驅動表了?跟我印象中對不上啊(哪本書上說leading引導的是驅動表),不管怎樣,先改改看

貌似這個就是我想要的執行計畫了,先掃瞄t2表,400多萬條資料全表掃一下還是挺快的,去session表關聯,由於是不等式連線,所以是索引範圍掃瞄,索引掃一下也很快。所以這個執行計畫時間複雜度是o(ip_temp+ip_temp*session),session是走索引所以速度非常快,

ip_temp*session時間可忽略不計。

再測試下,這回4秒鐘就出來了

可見執行計畫多麼的重要。

還有些困惑的地方,cbo為啥要搞出這麼個執行計畫(乙個key過濾乙個key連線)?為啥做了隱式轉換?做個10053可能可以搞出來。

oracle資料庫限制IP訪問

通過修改oracle資料庫的ora配置檔案可以實現只有指定ip才能訪問 開啟oracle安裝路徑下 dbhome 1 network admin sqlnet.ora檔案 增加以下 1.tcp.validnode checking yes 開啟ip限制功能 2.tcp.invited nodes 1...

ORACLE 限制特定IP訪問資料庫

1 在9i中真正起作用的是sqlnet.ora檔案,我們修改sqlnet.ora其實是最好最快的方法。在sqlnet.ora中增加如下部分 來自 protocol.ora 的屬性 tcp.validnode checking yes 允許訪問的ip tcp.invited nodes ip1,ip2...

爬取西刺ip的插入資料庫相關問題

今晚解決了前幾天爬取西刺ip網不能插入資料庫的問題,成功爬取並插入資料庫的 如下 encoding utf 8 import re import requests from scrapy.selector import selector import mysqldb conn mysqldb.con...