准備寫點扯淡些的博客,然后想了好半天,終於想到了個稍微有點文藝的標題,不喜勿噴啊,噴着我這里到處都是就不好拉。。。
一:場景
先說說場景吧,為了不過分暴露業務,就用字母代替下吧,半個月前業務那邊報了個bug,說根據A條件和B條件篩選一批數據,
當把時間(C條件)范圍拉小點,可以篩選出數據,把(C條件)時間拉大點,就沒有數據了。
二:分析
乍一看,泥煤的。。。真的有點神奇哦,0-24點可以拉到數據,0-12點反而就拉不到了,暈。。。。然后就仔細分析了下代碼,
然來不知道哪一個程序員在M庫里根據各種條件篩選出了20條數據,因為B條件在N庫里面,所以他拿着這20條數據到N庫去做篩選,
結果20條數據全部暴斃,最后就拿着空集合送到前台了。。。問題泥煤的終於明白了,就是如何根據多條件去做跨服務器查詢。
三:探索
其實也挺悲劇的,從業快四年了也沒遇到這個問題,雖然在上一家公司數據庫做了主從復制,跨庫,尼瑪的。。。也沒有跨服務
器查詢呀。。。不過那天問題找到后也挺興奮的,轉了轉珠子想了個辦法,用多線程搞一搞。。。
四: 失敗的一次嘗試
由於開發人員接觸不了生產,要是查的話還要找二線人員。。。我人又懶,不想郵件啥的通知人家,然后就自己假象了下數據應該
不會超過多少條。。。后來就是因為這個應該導致了該解決方法的失敗。
步驟如下:
①: 我那時假象一天的數據應該不會超過5w吧,為了加速,我准備多開幾個線程,一個線程撈tmd的5000條數據,5w的話我就開
10個線程。10w的話就開20個線程,反正線程是隨數據變的。
②: 就這樣我分別從M和N庫中撈出來我也不知道多少個OrderID,然后在兩組OrderID里面求個交集,當然這個要注意了,從數據
結構的角度說,這個需要用hash來去重,復雜度O(M+N),當我看到C#自帶的intersect就是先灌到hash里面做的,我就放
心了,至少不會出現惡心的O(MN)的復雜度了。。。
③: 求交集后,我現在就拿到一組OrderID了,然后拿這些orderID在內存中分頁,取出20條OrderID后再到主庫M中去查真正我需
要的數據,最后把數據送到前台上。。。
這些想法在我腦子里面遨游之后,我就啪啪啪的寫完了代碼,測試環境下也通過了。。。然后屁顛屁顛的上生產了,就這樣噩夢開始了。。。
過了個星期,業務過來說:這下好了,原先數據查不出來,現在你給我頁面報錯了,我說:暈,不會吧,我馬上去看看。。。查了下后,然來
發現是頁面執行時間過長,iis超時了。。。唉,這下沒法子了,去找二線查了下數據,居然N庫中有26w的數據,那我得要開52個線程,暈死,
我不知道當時生產環境的cpu狂飆的有木有。。。苦逼呀。。。還得繼續扣這些猥瑣的代碼。。。
五: 再次尋找解決方案
1:使用opendatasource跨服務器查詢
剛才我也寒酸的分析了下5個where,有4個在M庫中,有1個在N庫中,那就用opendatasource來做遠程服務器的inner join吧。。。
也許是公司為了性能和安全性考慮,禁用了此種使用方式,沒撤,此方案破產。。。
2: 做數據的冗余
泥煤的,把我逼到絕境了。。。既然跨不了服務器,那也只能做數據冗余了,沒辦法,只能在M庫里面建立一張冗余表,將N庫中表的數
據導入到這張冗余表吧,然后我就可以堂堂正正的用sql直接inner join了,問題也就差不多解決了,說干就干吧。
<1>事前冗余
我准備在web端插入數據的時候再冗余到XX表中,雖然是個過得去的主意,但是web端太多了,你懂的,要是為了這個小功能,要去改動無
數個的web端,工作量有點大了,還不知道人家部門配合不配合。。。而且我的需求也比較特殊,需要等M庫具有某些操作的時候,N庫中的
表才會生成數據,所以該種方案想想還是放棄了。。。
<2>事后冗余
后來還是決定用jobws每個小時去定時撈N庫中的數據,然后放入M庫的冗余表中,雖然業務那邊看的可能不是最新的一個小時的數據,
但是沒關系,這些數據不需要實時的,只要保證是最近一天的就足夠了,最后也就決定這種可行點了。。。悲劇啊。。。啊啊啊啊啊。。。
突然發現博客好像沒這么扯蛋過。。。還好蛋都扯完了,不過這也算是一個非常經典的問題,如果大家有什么好招數,記得分享分享
啊。。。謝謝了。。。。