SQL拆分实现与注意事项
SQL拆分的背景
任何系統的設計都是在不斷的迭代中改進的,在系統最初的階段,能夠最快的完成功能是首要任務,這就會導致我們在寫數據查詢時使用了大量的關聯查詢。而當系統用戶慢慢增加到我們不得不分庫分表的時候,原先的關聯查詢就會失效,這就迫使我們不得不將之前的關聯查詢拆分開,然后利用代碼邏輯進行關聯操作。
如何拆分SQL(left join 拆分)
其實,各種關聯操作的拆分思想基本是一樣的,只是在不同的情況下,我們可能會忽略掉某些問題而出錯。所以我只說了除了第一個left操作。
原SQL:SELECT u.* ,o.time FROM user u LEFT JOIN order o ON o.userId = u.id
拆分步驟:
簡化拆分工作的辦法是,寫一個工具類,根據自身的項目情況,針對性的寫出left 、inner、in、groupby、分頁、orderby等函數的公共方法
拆分注意事項
1.關聯子表有篩選條件的left join,在代碼里的 left join操作需要變成inner join操作
原SQL:
SELECT u.* ,o.time FROM user u LEFT JOIN order o ON o.userId = u.id WHERE o.time>‘2019-3-14 AND u.id BETWEEN 100 AND 1000’
拆分偽代碼:
List list1 = "SELECT u.* FROM user WHERE id BETWEEN 100 AND 1000’;
List list2 = "SELECT o.userId FROM order WHERE o.time>'2019-3-14 AND o.userId IN ( list1里的所有ID) ";
List result = list2與list1作inner join操作(而不是left 操作)
這是因為子表有條件之后,將不再以主表的數據為準了
2. 關聯子表會將主表的數據篩選掉的情況(不論是inner、left), 分頁操作需要將兩個表的數據拿到后在代碼里分頁
注:強烈不推薦在代碼里分頁,在代碼里分頁的最大問題是處理數據量會很大,會影響系統性能。
如果有分頁,盡量想辦法在SQL里完成;實在不行,可根據具體情況分析避免。
3. 如果主表與子表是 一對多的關系(不論是inner、left),子表的數據條數決定了主表的數據條數。
這個體現在代碼里就是,在利用map建立主表與子表的對應關系時,我們可以用ArrayListMultimap:
偽代碼:
4. 在作in操作時特別需要注意, 如果in的參數個數為0,則不再需要查SQL。
5. 要判斷in條件參數個數,如果太大會報導致報錯(這會是一個隱藏bug,直到數據量大了才會發現)。目前的解決辦法分成多次in查詢(太慢可考慮線程)
多線程in查詢可參考:https://gitee.com/lovewx/codes/be51427wngzfrcmqsivua79
6. 拆分SQL時,要考慮索引失效的問題,即關聯查詢時可以用到索引,而拆開之后就不能用到索引了
總結
以上是生活随笔為你收集整理的SQL拆分实现与注意事项的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql锁相关讲解及其应用——《深究m
- 下一篇: Java锁详解之ReentrantLoc