[prev in list] [next in list] [prev in thread] [next in thread] 

List:       monetdb-checkins
Subject:    MonetDB: Apr2019 - used patch from feature request Bug 6326, add...
From:       Niels Nes <commits+niels=cwi.nl () monetdb ! org>
Date:       2019-01-30 11:31:31
Message-ID: hg.2c50b80d80c7.1548847891.6315528441665844383 () monetdb-vm0 ! spin-off ! cwi ! nl
[Download RAW message or body]

Changeset: 2c50b80d80c7 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=2c50b80d80c7
Modified Files:
	sql/backends/monet5/sql_cat.c
	sql/backends/monet5/sql_statistics.c
	sql/backends/monet5/sql_statistics.h
	sql/server/rel_optimizer.c
	sql/server/rel_optimizer.h
Branch: Apr2019
Log Message:

used patch from feature request Bug 6326, added cleanup of the
statistics on changing the access (read only vs read write)


diffs (219 lines):

diff --git a/sql/backends/monet5/sql_cat.c b/sql/backends/monet5/sql_cat.c
--- a/sql/backends/monet5/sql_cat.c
+++ b/sql/backends/monet5/sql_cat.c
@@ -19,6 +19,7 @@
 #include "sql_mvc.h"
 #include "sql_qc.h"
 #include "sql_partition.h"
+#include "sql_statistics.h"
 #include "mal_namespace.h"
 #include "opt_prelude.h"
 #include "querylog.h"
@@ -386,7 +387,7 @@ alter_table_del_table(mvc *sql, char *ms
 }
 
 static char *
-alter_table_set_access(mvc *sql, char *sname, char *tname, int access)
+alter_table_set_access(Client cntxt, mvc *sql, char *sname, char *tname, int access)
 {
 	sql_schema *s = mvc_bind_schema(sql, sname);
 	sql_table *t = NULL;
@@ -401,6 +402,8 @@ alter_table_set_access(mvc *sql, char *s
 				throw(SQL,"sql.alter_table_set_access",SQLSTATE(40000) "ALTER TABLE: set READ or \
INSERT ONLY not possible with outstanding updates (wait until updates are \
flushed)\n");  
 			mvc_access(sql, t, access);
+			if (access == 0)
+				sql_drop_statistics(cntxt, t);
 		}
 	} else {
 		throw(SQL,"sql.alter_table_set_access",SQLSTATE(42S02) "ALTER TABLE: no such table \
'%s' in schema '%s'", tname, sname); @@ -1504,7 +1507,7 @@ SQLalter_set_table(Client \
cntxt, MalBlkP  int access = *getArgReference_int(stk, pci, 3);
 
 	initcontext();
-	msg = alter_table_set_access(sql, sname, tname, access);
+	msg = alter_table_set_access(cntxt, sql, sname, tname, access);
 
 	return msg;
 }
diff --git a/sql/backends/monet5/sql_statistics.c \
                b/sql/backends/monet5/sql_statistics.c
--- a/sql/backends/monet5/sql_statistics.c
+++ b/sql/backends/monet5/sql_statistics.c
@@ -55,6 +55,29 @@ strToStrSQuote(char **dst, size_t *len, 
 }
 
 str
+sql_drop_statistics(Client cntxt, sql_table *t)
+{
+	node *ncol;
+	char *dquery, *msg;
+
+	dquery = (char *) GDKzalloc(96);
+	if (dquery == NULL) {
+		throw(SQL, "analyze", SQLSTATE(HY001) MAL_MALLOC_FAIL);
+	}
+	if (isTable(t) && t->columns.set) {
+		for (ncol = (t)->columns.set->h; ncol; ncol = ncol->next) {
+			sql_column *c = ncol->data;
+
+			snprintf(dquery, 96, "delete from sys.statistics where \"column_id\" = %d;", \
c->base.id); +			msg = SQLstatementIntern(cntxt, &dquery, "SQLanalyze", TRUE, FALSE, \
NULL); +			if (msg)
+				return msg;
+		}
+	}
+	return NULL;
+}
+
+str
 sql_analyze(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
 {
 	mvc *m = NULL;
diff --git a/sql/backends/monet5/sql_statistics.h \
                b/sql/backends/monet5/sql_statistics.h
--- a/sql/backends/monet5/sql_statistics.h
+++ b/sql/backends/monet5/sql_statistics.h
@@ -25,5 +25,6 @@
 #endif
 
 sql5_export str sql_analyze(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr \
pci); +sql5_export str sql_drop_statistics(Client cntxt, sql_table *t);
 
 #endif /* _SQL_STATISTICS_DEF */
diff --git a/sql/server/rel_optimizer.c b/sql/server/rel_optimizer.c
--- a/sql/server/rel_optimizer.c
+++ b/sql/server/rel_optimizer.c
@@ -51,7 +51,7 @@ static sql_subfunc *find_func( mvc *sql,
 
 /* currently we only find simple column expressions */
 void *
-name_find_column( sql_rel *rel, char *rname, char *name, int pnr, sql_rel **bt ) 
+name_find_column( sql_rel *rel, const char *rname, const char *name, int pnr, \
sql_rel **bt )   {
 	sql_exp *alias = NULL;
 	sql_column *c = NULL;
@@ -8455,6 +8455,103 @@ rel_merge_table_rewrite(int *changes, mv
 	return rel;
 }
 
+static sql_rel*
+exp_skip_output_parts(sql_rel *rel)
+{
+	while ((is_topn(rel->op) || is_project(rel->op) || is_sample(rel->op)) && rel->l) {
+		if (rel->op == op_groupby && list_empty(rel->r))
+			return rel;			/* a group-by with no columns is a plain aggregate and hence always \
returns one row */ +		rel = rel->l;
+	}
+	return rel;
+}
+
+/* return true if the given expression is guaranteed to have no rows */
+static int
+exp_is_zero_rows(mvc *sql, sql_rel *rel, sql_rel *sel)
+{
+	sql_table *t;
+	node *n;
+
+	if (!rel)
+		return 0;
+	rel = exp_skip_output_parts(rel);
+	if (is_select(rel->op) && rel->l) {
+		sel = rel;
+		rel = exp_skip_output_parts(rel->l);
+	}
+	if (!sel)
+		return 0;
+	if (rel->op == op_join)
+		return exp_is_zero_rows(sql, rel->l, sel) || exp_is_zero_rows(sql, rel->r, sel);
+	if (rel->op == op_left || is_semi(rel->op))
+		return exp_is_zero_rows(sql, rel->l, sel);
+	if (rel->op == op_right)
+		return exp_is_zero_rows(sql, rel->r, sel);
+	if (!is_basetable(rel->op) || !rel->l)
+		return 0;
+	t = rel->l;
+	if (!isTable(t) || t->access != TABLE_READONLY)
+		return 0;
+
+	if (sel->exps) for (n = sel->exps->h; n; n = n->next) {
+		sql_exp *e = n->data;	
+		atom *lval = NULL, *hval = NULL;
+
+		if (e->type == e_cmp && (e->flag == cmp_equal || e->f)) {   /* half-ranges are \
theoretically optimizable here, but not implemented */ +			sql_exp *c = e->l;
+			if (c->type == e_column) {
+				sql_exp *l = e->r;
+				sql_exp *h = e->f;
+
+				lval = exp_flatten(sql, l);
+				hval = h ? exp_flatten(sql, h) : lval;
+				if (lval && hval) {
+					sql_rel *bt;
+					sql_column *col = name_find_column(sel, c->rname, c->name, -2, &bt);
+					void *min, *max;
+					if (col
+						&& col->t == t
+						&& sql_trans_ranges(sql->session->tr, col, &min, &max)
+						&& !exp_range_overlap(sql, c, min, max, lval, hval)) {
+						return 1;
+					}
+				}
+			}
+		}
+	}
+	return 0;
+}
+
+/* discard sides of UNION or UNION ALL which cannot produce any rows, as per
+statistics, similarly to the merge table optimizer, e.g.
+	select * from a where x between 1 and 2 union all select * from b where x between 1 \
and 2 +->	select * from b where x between 1 and 2   [assuming a has no rows with \
1<=x<=2] +*/
+static sql_rel *
+rel_remove_union_partitions(int *changes, mvc *sql, sql_rel *rel) 
+{
+	if (!is_union(rel->op))
+		return rel;
+	if (exp_is_zero_rows(sql, rel->l, NULL)) {
+		sql_rel *r = rel->r;
+		rel->r = NULL;
+		rel_destroy(rel);
+		(*changes)++;
+		sql->caching = 0;
+		return r;
+	}
+	if (exp_is_zero_rows(sql, rel->r, NULL)) {
+		sql_rel *l = rel->l;
+		rel->l = NULL;
+		rel_destroy(rel);
+		(*changes)++;
+		sql->caching = 0;
+		return l;
+	}
+	return rel;
+}
+
 /* TODO move all apply related stuff in to rel_apply.c/h */
 static int exps_uses_exps(list *users, list *exps);
 
@@ -9552,6 +9649,9 @@ optimize_rel(mvc *sql, sql_rel *rel, int
 	if (gp.cnt[op_select])
 		rel = rewrite_topdown(sql, rel, &rel_push_select_down_union, &changes); 
 
+	if (gp.cnt[op_union] && gp.cnt[op_select])
+		rel = rewrite(sql, rel, &rel_remove_union_partitions, &changes); 
+
 	if (gp.cnt[op_groupby]) {
 		rel = rewrite_topdown(sql, rel, &rel_push_aggr_down, &changes);
 		rel = rewrite_topdown(sql, rel, &rel_push_groupby_down, &changes);
diff --git a/sql/server/rel_optimizer.h b/sql/server/rel_optimizer.h
--- a/sql/server/rel_optimizer.h
+++ b/sql/server/rel_optimizer.h
@@ -16,7 +16,7 @@ extern sql_rel * rel_optimizer(mvc *sql,
 
 extern int exp_joins_rels(sql_exp *e, list *rels);
 
-extern void *name_find_column( sql_rel *rel, char *rname, char *name, int pnr, \
sql_rel **bt ); +extern void *name_find_column( sql_rel *rel, const char *rname, \
const char *name, int pnr, sql_rel **bt );  
 extern sql_rel * rel_dce(mvc *sql, sql_rel *rel);
 
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic