From 96656cf0c092303e85cbd46c40b8922e6b290c36 Mon Sep 17 00:00:00 2001 From: Shiwani Mishra Date: Tue, 31 Mar 2026 16:16:29 +0530 Subject: [PATCH] perf: eliminate N+1 queries in __make_cre_links and __get_all_nodes_and_cres MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit __make_cre_links was issuing a separate SELECT for each linked node — one query to fetch all Links rows for a CRE, then one more per row to fetch the corresponding Node. Replace with a single JOIN query so the whole thing resolves in one round-trip regardless of how many links a CRE has. __get_all_nodes_and_cres was fetching IDs first (SELECT id FROM …) and then re-querying each record individually. For CREs this chained into get_cre_by_db_id, which added a further SELECT external_id per CRE before finally calling get_CREs. Fetch full ORM objects directly and call get_CREs(external_id=) using the already-known external_id, cutting out that extra per-CRE round-trip. The same IDs-first pattern is fixed for the node branch. --- application/database/db.py | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/application/database/db.py b/application/database/db.py index d4ac9b7e8..045411c18 100644 --- a/application/database/db.py +++ b/application/database/db.py @@ -870,16 +870,14 @@ def __get_all_nodes_and_cres( self, cres_only: bool = False ) -> List[cre_defs.Document]: result = [] - nodes = [] - cres = [] if not cres_only: - node_ids = self.session.query(Node.id).all() - for nid in node_ids: - result.extend(self.get_nodes(db_id=nid[0])) + for node in self.session.query(Node).all(): + result.extend(self.get_nodes(db_id=node.id)) - cre_ids = self.session.query(CRE.id).all() - for cid in cre_ids: - result.append(self.get_cre_by_db_id(cid[0])) + for cre in self.session.query(CRE).all(): + cres = self.get_CREs(external_id=cre.external_id) + if cres: + result.append(cres[0]) return result @classmethod @@ -1334,9 +1332,14 @@ def __make_cre_links( self, cre: CRE, include_only_nodes: List[str] ) -> List[cre_defs.Link]: links = [] - for link in self.session.query(Links).filter(Links.cre == cre.id).all(): - node = self.session.query(Node).filter(Node.id == link.node).first() - if node and (not include_only_nodes or node.name in include_only_nodes): + rows = ( + self.session.query(Links, Node) + .join(Node, Node.id == Links.node) + .filter(Links.cre == cre.id) + .all() + ) + for link, node in rows: + if not include_only_nodes or node.name in include_only_nodes: links.append( cre_defs.Link( ltype=cre_defs.LinkTypes.from_str(link.type),