iT邦幫忙

2

關於MySQL JOIN兩個資料表運算時間達到50分鐘 TIME OUT 一百萬筆資料

  • 分享至 

  • xImage

系統:
WIN10
MYSQL 8
需求:
有兩個資料表
一個是台中門牌及經緯度大約120萬筆資料
另一個是公司內部客戶的檔案 約1萬筆(測試用)
只需要客戶資料表的地址跟台中資料表有符合
顯示該筆地址 及台中資料表裡的座標跟一些相關欄位

問題:
以上是我的SQL寫法
因沒遇過這麼大資料量的 所以也不清楚這速度是否是正常的
原本2000筆的時候就大概要15分鐘了
https://ithelp.ithome.com.tw/upload/images/20221116/20148353bPWMS94p0E.jpg

	SELECT addr.計算地址,addr.客編,`111年8月台中gis門牌_twd97+經緯度`.地址,`111年8月台中gis門牌_twd97+經緯度`.TWD97橫坐標,`111年8月台中gis門牌_twd97+經緯度`.TWD97縱坐標
	FROM addr
	JOIN `111年8月台中gis門牌_twd97+經緯度`   
	ON addr.`計算地址` LIKE `111年8月台中gis門牌_twd97+經緯度`.`地址`
	INTO OUTFILE "E:\output.csv" 
	CHARACTER SET big5 ;

想請教各位大大 是否有能優化的方式 或是其他方法(目前是要求使用MySQL stored procedure)

看更多先前的討論...收起先前的討論...
johncoc iT邦新手 3 級 ‧ 2022-11-16 18:24:04 檢舉
有需要用到like嗎,兩邊都是地址,用等號就可以比對了吧,精確度都一樣的話,like跟等號的結果是一樣的
win895564 iT邦新手 1 級 ‧ 2022-11-17 08:51:31 檢舉
因為不知道是不是自己的資料結構問題
抑或是語法上的問題 所以當下是用LIKE來試試看會不會比較快
地址 是中文吧,假如是中文,我建議樓主拆地址來查詢會比較好,例如地址是東區,那只去JOIN 東區的就好,不要JOIN台中全區的,全區120萬筆,也許東區只有五萬筆,那找五萬筆跟找 120萬筆 速度差很多,接下來嫌五萬太慢,還有看有沒有郵遞區號這一欄,如果可以郵遞區號,那更好,一個五碼區號,大概就幾千筆而已,這樣速度不是更快
win895564 iT邦新手 1 級 ‧ 2022-11-17 14:05:34 檢舉
了解 明白了 看來還有需要學習的地方 感謝
kinhp iT邦新手 5 級 ‧ 2022-11-22 14:21:10 檢舉
記得先用這個去解析台灣地址,再存進資料庫
https://github.com/arters/TaiwanAddressNER
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
2
海綿寶寶
iT邦大神 1 級 ‧ 2022-11-16 22:25:43
最佳解答

兩年前有類似的問題
答案是:ElasticSearch

win895564 iT邦新手 1 級 ‧ 2022-11-17 08:50:51 檢舉

我再來仔細閱讀看看
感謝大大
我應該認真爬文才對

3
poison3804
iT邦新手 4 級 ‧ 2022-11-16 17:51:17

用like搜尋本身效率就不會太好,畢竟每一筆都要去檢核過一次,
然後用筆數多的去join筆數少的應該也可以增加些效能,
因為這樣每一筆只要比對一萬次就可以得到結果,
比起每一筆要比對120萬次還要來得快很多才對。

其他做法就是盡量先縮小要搜尋的範圍,再來join也可以增加效率。

win895564 iT邦新手 1 級 ‧ 2022-11-16 18:01:20 檢舉

小弟還太淺
因為我是想說 join 的部分
兩邊不是等於都要一起比對
這樣不是筆數都是一樣

3
雷峰
iT邦研究生 1 級 ‧ 2022-11-16 19:29:38

建議先大兩個資料庫新增一些欄位做群組分類,然後從群組來做篩選。
111年8月台中GIS門牌TWD97+經緯度,有下面這些欄位:
省市縣市代碼,鄉鎮市區代碼,村里,鄰,街路段,地區,巷,弄,號,TWD97橫坐標,TWD97縱坐標,WGS84經度,WGS84緯度.
客戶資料表不知道有哪些欄位,建議這個資料表欄位先處理到跟上面欄位類似,然後再去下筆對的動作.
這樣篩選出同一個「村里」或是「鄰」之後再比對的話,要比對資料就不會這麽多了@@

看更多先前的回應...收起先前的回應...
ckp6250 iT邦好手 1 級 ‧ 2022-11-16 19:37:26 檢舉

+1
虛擬欄位+索引,可以解決這個問題。
無論如何 120 萬對上 1 萬筆,都不需要這麼久。

win895564 iT邦新手 1 級 ‧ 2022-11-17 08:54:15 檢舉

抱歉 我補充一下
我客戶資料表上 原本只有地址
有拆分為不同欄位
以及將原地址做一些標準化處理
最後一句我能理解 但是該如何著手呢
謝謝

ckp6250 iT邦好手 1 級 ‧ 2022-11-17 10:51:24 檢舉

長遠之計,是否您的客戶基本資料裡,就應有【TWD97橫坐標】和【TWD97縱坐標】這二個欄位,然後,在stored procedure中,當新增或更改客戶資料時,直接寫入其值,這樣就不必用 join 浪費時間了。
(座標應該不可能會變動吧)

如果這樣規畫的話,每次增修,您只要搜尋一次即可。

win895564 iT邦新手 1 級 ‧ 2022-11-17 11:51:51 檢舉

不好意思 我說的不太明白
最終結果是
偶爾會往台中資料表加入新的地址(有經緯度)
客戶資料表資料也會加(只有地址,其他欄位是後面標準化增加的)(經緯度欄位無資料)
所以需要台中資料表跟客戶資料表的地址欄位比對相同
那麼客戶資料表的經緯度欄位會從台中資料表加入經緯到到客戶資料表

win895564 iT邦新手 1 級 ‧ 2022-11-17 11:53:38 檢舉

求大大能否給個開頭關於stored procedure的部分 感謝
因為stored procedure 是開始寫這個的時候才接觸
不過新增資料 也可以加判斷式嗎
是使用觸發器嗎

ckp6250 iT邦好手 1 級 ‧ 2022-11-21 20:33:53 檢舉

是觸發器沒錯。

2

海綿給你的那篇,其實我也有回答。

先做到基本的幾件事

1.不要用中文欄位名:此動作是要降低索引資料容量。資料容量少相對的搜尋就會比較快。
2.不要用LIKE ORDER 且也不盡量不要使用到 GROUP。

LIKE或ORDER,會造成全表搜尋的動作出現。所以當表資料屬於百萬級的。
使用LIKE是一件很蠢的事。

善用子查尋處理
認真來說,其實會變慢的主要原因,大多還是因為資料數量。就算有做好索引的情況下。
當資料達到百萬千萬級時。就要考量如何做資料分流了

win895564 iT邦新手 1 級 ‧ 2022-11-18 10:27:49 檢舉

了解 我後來有嘗試使用explain 並且去做一些語法上的調整
效能差異很大 也學到很多
雖然還能更好 但至少不用在電腦面前苦苦等
感謝大大!

我要發表回答

立即登入回答