From 967e5805beb12fb81462775e286f27301f74c9bc Mon Sep 17 00:00:00 2001 From: shparkcubrid Date: Mon, 29 Aug 2022 13:38:55 +0900 Subject: [PATCH 1/4] add count only optimiztion for join --- src/query/query_executor.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/query/query_executor.c b/src/query/query_executor.c index 4bfbed2f457..4cf3df8851f 100644 --- a/src/query/query_executor.c +++ b/src/query/query_executor.c @@ -7861,22 +7861,38 @@ qexec_intprt_fnc (THREAD_ENTRY * thread_p, XASL_NODE * xasl, XASL_STATE * xasl_s } agg_ptr = buildvalue->agg_list; - if (!xasl->scan_ptr /* no scan procedure */ - && !xasl->fptr_list /* no path expressions */ + /* check only one count(*) function + * TO_DO : this routine can be moved to XASL generator */ + if (!xasl->fptr_list /* no path expressions */ && !xasl->if_pred /* no if predicates */ && !xasl->instnum_pred /* no instnum predicate */ && agg_ptr->next == NULL /* no other aggregate functions */ && agg_ptr->function == PT_COUNT_STAR) { - /* only one count(*) function */ - ACCESS_SPEC_TYPE *specp = xasl->spec_list; + ACCESS_SPEC_TYPE *specp; + bool is_scan_ptr = xasl->scan_ptr ? true : false; + /* get last scan_ptr */ + xptr = xasl; + while (xptr->scan_ptr) + { + xptr = xptr->scan_ptr; + } + specp = xptr->spec_list; + assert (specp); + + /* count(*) query will scan an index but does not have a data-filter */ if (specp->next == NULL && specp->access == ACCESS_METHOD_INDEX && specp->s.cls_node.cls_regu_list_pred == NULL && specp->where_pred == NULL && !specp->indexptr->use_iss && !SCAN_IS_INDEX_MRO (&specp->s_id.s.isid)) { - /* count(*) query will scan an index but does not have a data-filter */ + /* there are two optimization for query having count() only + * 1. Skip saving data to temporary files. + * 2. Skip iteration for each index keys (no scan ptr only) */ specp->s_id.s.isid.need_count_only = true; - count_star_with_iscan_opt = true; + if (!is_scan_ptr) + { + count_star_with_iscan_opt = true; + } } } } From 62ad5353f6b67937958e505e99564d785bf3f792 Mon Sep 17 00:00:00 2001 From: shparkcubrid Date: Mon, 29 Aug 2022 17:09:12 +0900 Subject: [PATCH 2/4] fix that query without join can only skip iteration for index keys --- src/query/query_executor.c | 4 +++- src/query/scan_manager.c | 13 +++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/query/query_executor.c b/src/query/query_executor.c index 4cf3df8851f..6f3ca9c1727 100644 --- a/src/query/query_executor.c +++ b/src/query/query_executor.c @@ -7958,8 +7958,10 @@ qexec_intprt_fnc (THREAD_ENTRY * thread_p, XASL_NODE * xasl, XASL_STATE * xasl_s if (count_star_with_iscan_opt) { + /* count only query without join can skip iteration for index keys */ + xasl->curr_spec->s_id.position = S_BEFORE; xasl->proc.buildvalue.agg_list->accumulator.curr_cnt += (&xasl->curr_spec->s_id)->s.isid.oids_count; - /* may have more scan ranges */ + /* may have more OIDs */ continue; } /* set scan item as qualified */ diff --git a/src/query/scan_manager.c b/src/query/scan_manager.c index 768454161a4..e284b0496ba 100644 --- a/src/query/scan_manager.c +++ b/src/query/scan_manager.c @@ -5812,15 +5812,14 @@ scan_next_index_scan (THREAD_ENTRY * thread_p, SCAN_ID * scan_id) return ret; } + scan_id->position = S_ON; + isidp->curr_oidno = 0; /* first oid number */ if (isidp->need_count_only == true) { /* no more scan is needed. just return */ return S_SUCCESS; } - scan_id->position = S_ON; - isidp->curr_oidno = 0; /* first oid number */ - if (SCAN_IS_INDEX_COVERED (isidp)) { qfile_close_list (thread_p, isidp->indx_cov.list_id); @@ -5857,6 +5856,12 @@ scan_next_index_scan (THREAD_ENTRY * thread_p, SCAN_ID * scan_id) if (isidp->curr_oidno < oids_cnt - 1) { isidp->curr_oidno++; + if (isidp->need_count_only == true) + { + /* no more scan is needed. just return */ + return S_SUCCESS; + } + if (!SCAN_IS_INDEX_COVERED (isidp)) { if (isidp->multi_range_opt.use) @@ -5927,13 +5932,13 @@ scan_next_index_scan (THREAD_ENTRY * thread_p, SCAN_ID * scan_id) return ret; } + isidp->curr_oidno = 0; /* first oid number */ if (isidp->need_count_only == true) { /* no more scan is needed. just return */ return S_SUCCESS; } - isidp->curr_oidno = 0; /* first oid number */ if (SCAN_IS_INDEX_COVERED (isidp)) { qfile_close_list (thread_p, isidp->indx_cov.list_id); From db22c75d1e009797f04339eb319c0d6944006f87 Mon Sep 17 00:00:00 2001 From: shparkcubrid Date: Tue, 30 Aug 2022 13:22:42 +0900 Subject: [PATCH 3/4] check if_pred of last scan_ptr --- src/query/query_executor.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/query/query_executor.c b/src/query/query_executor.c index 6f3ca9c1727..bdc6c89bd01 100644 --- a/src/query/query_executor.c +++ b/src/query/query_executor.c @@ -7864,7 +7864,6 @@ qexec_intprt_fnc (THREAD_ENTRY * thread_p, XASL_NODE * xasl, XASL_STATE * xasl_s /* check only one count(*) function * TO_DO : this routine can be moved to XASL generator */ if (!xasl->fptr_list /* no path expressions */ - && !xasl->if_pred /* no if predicates */ && !xasl->instnum_pred /* no instnum predicate */ && agg_ptr->next == NULL /* no other aggregate functions */ && agg_ptr->function == PT_COUNT_STAR) @@ -7883,7 +7882,8 @@ qexec_intprt_fnc (THREAD_ENTRY * thread_p, XASL_NODE * xasl, XASL_STATE * xasl_s /* count(*) query will scan an index but does not have a data-filter */ if (specp->next == NULL && specp->access == ACCESS_METHOD_INDEX && specp->s.cls_node.cls_regu_list_pred == NULL && specp->where_pred == NULL - && !specp->indexptr->use_iss && !SCAN_IS_INDEX_MRO (&specp->s_id.s.isid)) + && !specp->indexptr->use_iss && !SCAN_IS_INDEX_MRO (&specp->s_id.s.isid) + && !xptr->if_pred /* no if predicates */) { /* there are two optimization for query having count() only * 1. Skip saving data to temporary files. From 80e714ed7ecac43a2b6d41f6bac2b406d52e79b1 Mon Sep 17 00:00:00 2001 From: shparkcubrid Date: Tue, 30 Aug 2022 13:40:53 +0900 Subject: [PATCH 4/4] indent --- src/query/query_executor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/query/query_executor.c b/src/query/query_executor.c index bdc6c89bd01..4382a445f9f 100644 --- a/src/query/query_executor.c +++ b/src/query/query_executor.c @@ -7883,7 +7883,7 @@ qexec_intprt_fnc (THREAD_ENTRY * thread_p, XASL_NODE * xasl, XASL_STATE * xasl_s if (specp->next == NULL && specp->access == ACCESS_METHOD_INDEX && specp->s.cls_node.cls_regu_list_pred == NULL && specp->where_pred == NULL && !specp->indexptr->use_iss && !SCAN_IS_INDEX_MRO (&specp->s_id.s.isid) - && !xptr->if_pred /* no if predicates */) + && !xptr->if_pred /* no if predicates */ ) { /* there are two optimization for query having count() only * 1. Skip saving data to temporary files.