關於樹結構的查詢優化,及許可權樹的查詢優化
在有限的經驗下,主要討論以下兩部分內容
1.對樹形資料結構的查詢,且層級較少,採用新增分級欄位的方式優化
2.針對前端使用ztree ,list直接返回結果集,存在授權問題的查詢,採用新增層次碼的方案
1.針對需要樹結構的查詢
-
在有限的多級目錄情況下,可以新增分級欄位,(1級目錄,2級目錄,3級目錄),
- 1.在這個基礎上假設只有三級目錄,那麼我們可以直接分3次查詢,此時得到了3個關於1、 2、 3層級對應的list;
- 2.上一步的操作,使我們極大的改善了資料庫查詢的效率,只需要3次查詢即可拿到所有的資料,但同樣,需要解決拼樹的問題
- 3.對樹的拼接,在目前大部分伺服器使用多核的情況下,推薦使用java8 Stream操作對原始list進行加工。
基於以上假設,單條資料如下,即正常查詢list中資料泛型為Regions
@Data
public class Regions {
private Integer objectId;//id
private String regionName;//區域名稱
private String regionCode;//區域編碼
private Integer level;//區域級別
private String parentCode;//上級區域編號
}
返回到頁面的物件
@Data
public class TreeNode {
private String regionName;
private String regionCode;
private String parentCode;
List<TreeNode> children;
}
演算法寫法
import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;
import static java.util.stream.Collectors.toList;
@Service
public class RegionServiceImpl implements RegionService {
@Resource
private RegionsMapper regionsMapper;
@Override
public List<TreeNode> getRegionTree() {
//根據層級關係查詢了3次
List<Regions> level1 = regionsMapper.getListByLevel(1);
List<Regions> level2 = regionsMapper.getListByLevel(2);
List<Regions> level3 = regionsMapper.getListByLevel(3);
//先將最末級轉為TreeNode 的形式
List<TreeNode> node3 = level3.stream().map(l3 -> {
TreeNode treeNode = new TreeNode();
treeNode.setRegionCode(l3.getRegionCode());
treeNode.setRegionName(l3.getRegionName());
treeNode.setParentCode(l3.getParentCode());
//沒有下級children 不做處理
return treeNode;
}).collect(toList());
//對二級目錄進行抽象
List<TreeNode> node2 = level2.stream().map(a -> {
TreeNode treeNode = new TreeNode();
treeNode.setRegionName(a.getRegionName());
treeNode.setRegionCode(a.getRegionCode());
treeNode.setParentCode(a.getParentCode());
treeNode.setChildren(node3.stream().filter(l3 -> l3.getParentCode().equals(a.getRegionCode())).collect(toList()));
return treeNode;
}).collect(toList());
//對一級目錄繼續抽象並返回
List<TreeNode> node1 = level1.stream().map(a -> {
TreeNode treeNode = new TreeNode();
treeNode.setRegionName(a.getRegionName());
treeNode.setRegionCode(a.getRegionCode());
treeNode.setParentCode(a.getParentCode());
treeNode.setChildren(node2.stream().filter(l2 -> l2.getParentCode().equals(a.getRegionCode())).collect(toList()));
return treeNode;
}).collect(toList());
return node1;
}
}
1000條資料,耗時1s多一點,這裡作者連的是遠端資料庫加上網速也不是很樂觀,若網路連線暢通,還會快一些。
備註 :若層級較多時,可以進一步簡化(抽象),以for迴圈的形式讀取每個層級的資料,然後以同樣以for迴圈的形式對資料進行從低到高的封裝,一個方法做迴圈層級讀取資料,另一個方法做對多個層級進行 樹的推導
2.針對zTree授權樹的查詢優化
-
前言:
-
前端使用zTree外掛時,可以進一步簡化後端的查詢,也不存在樹的結構化返回,實際上,如果沒有許可權的管理,我們只需要拿到所有的資料,並對資料欄位進行取別名,使其符合zTree的規範即可。
-
當目錄層級存在許可權時,比如子目錄存在許可權,但父目錄並沒有授權,但在前端介面中,我們同樣需要載入父級目錄顯示給使用者,以維持整個目錄的結構。
-
思考
理論上,我們從上往下進行遞迴,每驗證一個目錄需要驗證 它 及它的子目錄 是否存在許可權,如果存在許可權,那麼就將這個目錄存放到list中,並繼續遞迴它的下級目錄
弊端 :當資料量較大時,其需要不斷查詢下級目錄,並不斷做驗證許可權的查詢,驗證 本級及下級是否存在許可權 理論上也需要做遞迴,這樣就導致了大量的查詢操作,使效率極大的被限制。 -
解決方案
加入層次碼(同樣是不可重複的)欄位,即 比如上級選單的層次碼為 xxx ,那麼下級選單的層次碼 必定為xxxyyy 或xxxzzz,並且它的多層子目錄的層次碼必定為xxx開頭。
基於以上的假設,我們的思路如下:-
1.查詢到所有的已授權目錄的層次碼,並標識為這樣的一個List 集合:
List<Authority> authList
Authority 主要欄位為 ccm(層次碼) -
2.查詢所有的目錄,即不管是否存在授權都進行查詢 ,存放於:
List<Menu> menus
,Menu的主要欄位是業務欄位,及ccm 欄位,注意menus 是可以直接返回到前端的一個list,我們現在要做的只是篩選授權的資料,並返回即可 -
3.使用java 8 Stream 方法,根據層次碼進行篩選,程式碼如下:
-
public List<Menus> getAuthroityMenus(){
List<Menus> menus = new ArrayList<>();//假設這裡查詢了資料庫,獲得了所有的目錄
List<Authority> authList = new ArrayList<>();//假設這裡查詢了資料庫,得到了所有授權的目錄
return menus.stream().filter(a->{
//a,表示每一個menu物件
//同樣的,下方的b 對應每一個Authority物件
//遍歷授權目錄,如果 授權目錄的ccm 以此刻的Menu.ccm 開頭,則表示這個menu是已授權的上級,
if (authList.stream().filter(b->b.getCcm().startsWith(a.getCcm())).count()>0){
return true;
}
return false;
}).collect(Collectors.toList());
}
java8 的寫法有不瞭解的可以搜下相關資料,博主自己也寫過一些java 8相關的內容,這裡就不做具體的細節介紹了。
有疑問或有其他更好的方法,也希望大家在評論區積極發言!
相關文章
- 樹形查詢也瘋狂&優化措施優化
- 關於分頁查詢的優化思路優化
- MySQL 索引及查詢優化總結MySql索引優化
- 查詢優化優化
- 關於資料字典的查詢效率優化優化
- MySQL 的查詢優化MySql優化
- Oracle:優化方法總結(關於連表查詢)Oracle優化
- mysql關聯查詢優化MySql優化
- TiDB 查詢優化及調優系列(四)查詢執行計劃的調整及優化原理TiDB優化
- pgsql查詢優化之模糊查詢SQL優化
- Oracle in 查詢優化Oracle優化
- MySQL查詢優化MySql優化
- join 查詢優化優化
- HBase查詢優化優化
- 查詢優化器優化
- SQL查詢優化SQL優化
- 一文讀懂MySQL的索引結構及查詢優化MySql索引優化
- Oracle許可權相關查詢Oracle
- 全文查詢的效能優化優化
- SQL查詢優化的方法SQL優化
- 聊聊mysql的樹形結構儲存及查詢MySql
- Hierarchical Queries 級聯查詢(樹狀結構查詢)
- mysql查詢效能優化總結MySql優化
- 關於樹型結構資料遞迴查詢,轉非遞迴查詢的實現遞迴
- NKMySQL 查詢樹結構方式gllMySql
- sql server的許可權查詢SQLServer
- 樹形結構的儲存與查詢
- Oracle 樹形結構查詢的特殊用法Oracle
- MySQL索引原理及慢查詢優化MySql索引優化
- 分頁查詢優化優化
- MySQL 慢查詢優化MySql優化
- KunlunDB 查詢優化(一)優化
- MySQL優化COUNT()查詢MySql優化
- 優化sql查詢速度優化SQL
- EntityFramework優化:查詢效能Framework優化
- EntityFramework優化:查詢WITH(NOLOCK)Framework優化
- 優化星型查詢優化
- mysql查詢優化檢查 explainMySql優化AI