Преглед изворни кода

:zap: 优化关系图生成性能 https://github.com/siyuan-note/siyuan/issues/7361

Liang Ding пре 2 година
родитељ
комит
d5e07318ee
3 измењених фајлова са 57 додато и 29 уклоњено
  1. 38 22
      kernel/model/graph.go
  2. 3 3
      kernel/sql/block_query.go
  3. 16 4
      kernel/sql/block_ref_query.go

+ 38 - 22
kernel/model/graph.go

@@ -93,8 +93,8 @@ func BuildTreeGraph(id, query string) (boxID string, nodes []*GraphNode, links [
 
 	var sqlBlocks []*sql.Block
 	var rootID string
-	if "NodeDocument" == block.Type {
-		sqlBlocks = sql.GetAllChildBlocks(block.ID, stmt)
+	if ast.NodeDocument == node.Type {
+		sqlBlocks = sql.GetAllChildBlocks([]string{block.ID}, stmt)
 		rootID = block.ID
 	} else {
 		sqlBlocks = sql.GetChildBlocks(block.ID, stmt)
@@ -106,22 +106,30 @@ func BuildTreeGraph(id, query string) (boxID string, nodes []*GraphNode, links [
 		if nil != rootBlock {
 			// 按引用处理
 			sqlRootDefs := sql.QueryDefRootBlocksByRefRootID(rootID)
-			for _, sqlRootDef := range sqlRootDefs {
-				rootDef := fromSQLBlock(sqlRootDef, "", 0)
+			rootDefBlocks := fromSQLBlocks(&sqlRootDefs, "", 0)
+			var rootIDs []string
+			for _, rootDef := range rootDefBlocks {
 				blocks = append(blocks, rootDef)
+				rootIDs = append(rootIDs, rootDef.ID)
+			}
+
+			sqlRootRefBlocks := sql.QueryRefRootBlocksByDefRootIDs(rootIDs)
+			for defRootID, sqlRefBlocks := range sqlRootRefBlocks {
+				rootBlock := getBlockIn(rootDefBlocks, defRootID)
+				if nil == rootBlock {
+					continue
+				}
 
-				sqlRootRefs := sql.QueryRefRootBlocksByDefRootID(sqlRootDef.ID)
-				rootRefs := fromSQLBlocks(&sqlRootRefs, "", 0)
-				rootDef.Refs = append(rootDef.Refs, rootRefs...)
+				refBlocks := fromSQLBlocks(&sqlRefBlocks, "", 0)
+				rootBlock.Refs = append(rootBlock.Refs, refBlocks...)
 			}
 
 			// 按定义处理
-			sqlRootRefs := sql.QueryRefRootBlocksByDefRootID(rootID)
-			for _, sqlRootRef := range sqlRootRefs {
-				rootRef := fromSQLBlock(sqlRootRef, "", 0)
-				blocks = append(blocks, rootRef)
-
-				rootBlock.Refs = append(rootBlock.Refs, rootRef)
+			sqlRootRefBlocks = sql.QueryRefRootBlocksByDefRootIDs([]string{rootID})
+			for _, sqlRefBlocks := range sqlRootRefBlocks {
+				blocks = append(blocks, rootBlock)
+				refBlocks := fromSQLBlocks(&sqlRefBlocks, "", 0)
+				rootBlock.Refs = append(rootBlock.Refs, refBlocks...)
 			}
 		}
 	}
@@ -157,22 +165,29 @@ func BuildGraph(query string) (boxID string, nodes []*GraphNode, links []*GraphL
 	if 0 < len(roots) {
 		boxID = roots[0].Box
 	}
+	var rootIDs []string
 	for _, root := range roots {
-		sqlBlocks := sql.GetAllChildBlocks(root.ID, stmt)
-		treeBlocks := fromSQLBlocks(&sqlBlocks, "", 0)
-		genTreeNodes(treeBlocks, &nodes, &links, false, style)
-		blocks = append(blocks, treeBlocks...)
+		rootIDs = append(rootIDs, root.ID)
+	}
+	rootIDs = gulu.Str.RemoveDuplicatedElem(rootIDs)
+
+	sqlBlocks := sql.GetAllChildBlocks(rootIDs, stmt)
+	treeBlocks := fromSQLBlocks(&sqlBlocks, "", 0)
+	genTreeNodes(treeBlocks, &nodes, &links, false, style)
+	blocks = append(blocks, treeBlocks...)
 
-		// 文档块关联
-		rootBlock := getBlockIn(treeBlocks, root.ID)
+	// 文档块关联
+	sqlRootRefBlocks := sql.QueryRefRootBlocksByDefRootIDs(rootIDs)
+	for defRootID, sqlRefBlocks := range sqlRootRefBlocks {
+		rootBlock := getBlockIn(treeBlocks, defRootID)
 		if nil == rootBlock {
 			continue
 		}
 
-		sqlRootRefs := sql.QueryRefRootBlocksByDefRootID(root.ID)
-		rootRefs := fromSQLBlocks(&sqlRootRefs, "", 0)
-		rootBlock.Refs = append(rootBlock.Refs, rootRefs...)
+		refBlocks := fromSQLBlocks(&sqlRefBlocks, "", 0)
+		rootBlock.Refs = append(rootBlock.Refs, refBlocks...)
 	}
+
 	growTreeGraph(&forwardlinks, &backlinks, &nodes)
 	blocks = append(blocks, forwardlinks...)
 	blocks = append(blocks, backlinks...)
@@ -651,6 +666,7 @@ func graphDailyNoteFilter(local bool) string {
 		return ""
 	}
 
+	dailyNotesPaths = gulu.Str.RemoveDuplicatedElem(dailyNotesPaths)
 	buf := bytes.Buffer{}
 	for _, p := range dailyNotesPaths {
 		buf.WriteString(" AND ref.hpath NOT LIKE '" + p + "%'")

+ 3 - 3
kernel/sql/block_query.go

@@ -535,13 +535,13 @@ func GetChildBlocks(parentID, condition string) (ret []*Block) {
 	return
 }
 
-func GetAllChildBlocks(rootID, condition string) (ret []*Block) {
+func GetAllChildBlocks(rootIDs []string, condition string) (ret []*Block) {
 	ret = []*Block{}
-	sqlStmt := "SELECT * FROM blocks AS ref WHERE ref.root_id = ?"
+	sqlStmt := "SELECT * FROM blocks AS ref WHERE ref.root_id IN ('" + strings.Join(rootIDs, "','") + "')"
 	if "" != condition {
 		sqlStmt += " AND " + condition
 	}
-	rows, err := query(sqlStmt, rootID)
+	rows, err := query(sqlStmt)
 	if nil != err {
 		logging.LogErrorf("sql query [%s] failed: %s", sqlStmt, err)
 		return

+ 16 - 4
kernel/sql/block_ref_query.go

@@ -157,16 +157,28 @@ func QueryDefRootBlocksByRefRootID(refRootID string) (ret []*Block) {
 	return
 }
 
-func QueryRefRootBlocksByDefRootID(defRootID string) (ret []*Block) {
-	rows, err := query("SELECT * FROM blocks WHERE id IN (SELECT DISTINCT root_id FROM refs WHERE def_block_root_id = ?)", defRootID)
+func QueryRefRootBlocksByDefRootIDs(defRootIDs []string) (ret map[string][]*Block) {
+	ret = map[string][]*Block{}
+
+	stmt := "SELECT r.def_block_root_id, b.* FROM refs AS r, blocks AS b ON r.def_block_root_id IN ('" + strings.Join(defRootIDs, "','") + "')" + " AND b.id = r.root_id"
+	rows, err := query(stmt)
 	if nil != err {
 		logging.LogErrorf("sql query failed: %s", err)
 		return
 	}
 	defer rows.Close()
 	for rows.Next() {
-		if block := scanBlockRows(rows); nil != block {
-			ret = append(ret, block)
+		var block Block
+		var defRootID string
+		if err := rows.Scan(&defRootID, &block.ID, &block.ParentID, &block.RootID, &block.Hash, &block.Box, &block.Path, &block.HPath, &block.Name, &block.Alias, &block.Memo, &block.Tag, &block.Content, &block.FContent, &block.Markdown, &block.Length, &block.Type, &block.SubType, &block.IAL, &block.Sort, &block.Created, &block.Updated); nil != err {
+			logging.LogErrorf("query scan field failed: %s\n%s", err, logging.ShortStack())
+			return
+		}
+
+		if nil == ret[defRootID] {
+			ret[defRootID] = []*Block{}
+		} else {
+			ret[defRootID] = append(ret[defRootID], &block)
 		}
 	}
 	return