Changeset: df4720521fce for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=df4720521fce
Modified Files:
        gdk/gdk_select.c
Branch: Nov2019
Log Message:

Rearrange select code for more optimal code paths.
- Use hashselect when we already have a hash, even when sorted or when
we also have an order index.
- Rebuild hash for persistent bats even when we have a candidate list
if using one is expected to be faster than a scan.


diffs (114 lines):

diff --git a/gdk/gdk_select.c b/gdk/gdk_select.c
--- a/gdk/gdk_select.c
+++ b/gdk/gdk_select.c
@@ -1376,7 +1376,7 @@ BATselect(BAT *b, BAT *s, const void *tl
        /* if equi set, then so are both lval and hval */
        assert(!equi || (lval && hval));
 
-       if (hval && ((equi && !(li && hi)) || ATOMcmp(t, tl, th) > 0)) {
+       if (hval && (equi ? !li || !hi : ATOMcmp(t, tl, th) > 0)) {
                /* empty range */
                bn = BATdense(0, 0, 0);
                ALGODEBUG fprintf(stderr, "#BATselect(b=" ALGOBATFMT
@@ -1516,12 +1516,40 @@ BATselect(BAT *b, BAT *s, const void *tl
                }
        }
 
-       /* If there is an order index or it is a view and the parent has an 
ordered
-        * index, and the bat is not tsorted or trevstorted then use the order
-        * index.
-        * And there is no cand list or if there is one, it is dense.
+       parent = VIEWtparent(b);
+       assert(parent >= 0);
+       /* use hash only for equi-join, and then only if b or its
+        * parent already has a hash, or if b or its parent is
+        * persistent and the total size wouldn't be too large; check
+        * for existence of hash last since that may involve I/O */
+       hash = equi &&
+               (BATcheckhash(b) ||
+                (!b->batTransient &&
+                 ATOMsize(b->ttype) >= sizeof(BUN) / 4 &&
+                 BATcount(b) * (ATOMsize(b->ttype) + 2 * sizeof(BUN)) < 
GDK_mem_maxsize / 2));
+       if (equi && !hash && parent != 0) {
+               /* use parent hash if it already exists and if either
+                * a quick check shows the value we're looking for
+                * does not occur, or if it is cheaper to check the
+                * candidate list for each value in the hash chain
+                * than to scan (cost for probe is average length of
+                * hash chain (count divided by #slots) times the cost
+                * to do a binary search on the candidate list (or 1
+                * if no need for search)) */
+               tmp = BBPquickdesc(parent, false);
+               hash = phash = tmp && BATcheckhash(tmp) &&
+                       (BATcount(tmp) == BATcount(b) ||
+                        BATcount(tmp) / ((size_t *) tmp->thash->heap.base)[5] 
* (s && !BATtdense(s) ? ilog2(BATcount(s)) : 1) < (s ? BATcount(s) : 
BATcount(b)) ||
+                        HASHget(tmp->thash, HASHprobe(tmp->thash, tl)) == 
HASHnil(tmp->thash));
+       }
+
+       /* If there is an order index or it is a view and the parent
+        * has an ordered index, and the bat is not tsorted or
+        * trevstorted then use the order index.  And there is no cand
+        * list or if there is one, it is dense.
         * TODO: we do not support anti-select with order index */
        if (!anti &&
+           !(hash && (phash || b->thash)) &&
            !(b->tsorted || b->trevsorted) &&
            (!s || (s && BATtdense(s)))    &&
            (BATcheckorderidx(b) ||
@@ -1554,7 +1582,8 @@ BATselect(BAT *b, BAT *s, const void *tl
                ALGODEBUG if (view && b != view) fprintf(stderr, "#BATselect: 
switch from " ALGOBATFMT " to " ALGOBATFMT " " OIDFMT "-" OIDFMT " off " LLFMT 
"\n", ALGOBATPAR(view), ALGOBATPAR(b), vwl, vwh, vwo);
        }
 
-       if (BATordered(b) || BATordered_rev(b) || use_orderidx) {
+       if (!(hash && (phash || b->thash)) &&
+           (BATordered(b) || BATordered_rev(b) || use_orderidx)) {
                BUN low = 0;
                BUN high = b->batCount;
 
@@ -1813,36 +1842,10 @@ BATselect(BAT *b, BAT *s, const void *tl
        }
        /* refine upper limit by exact size (if known) */
        maximum = MIN(maximum, estimate);
-       parent = VIEWtparent(b);
-       assert(parent >= 0);
-       /* use hash only for equi-join, and then only if b or its
-        * parent already has a hash, or if b or its parent is
-        * persistent and the total size wouldn't be too large; check
-        * for existence of hash last since that may involve I/O */
-       hash = equi &&
-               ((!b->batTransient &&
-                 ATOMsize(b->ttype) >= sizeof(BUN) / 4 &&
-                 BATcount(b) * (ATOMsize(b->ttype) + 2 * sizeof(BUN)) < 
GDK_mem_maxsize / 2) ||
-                BATcheckhash(b));
-       if (equi && !hash && parent != 0) {
-               /* use parent hash if it already exists and if either
-                * a quick check shows the value we're looking for
-                * does not occur, or if it is cheaper to check the
-                * candidate list for each value in the hash chain
-                * than to scan (cost for probe is average length of
-                * hash chain (count divided by #slots) times the cost
-                * to do a binary search on the candidate list (or 1
-                * if no need for search)) */
-               tmp = BBPquickdesc(parent, false);
-               hash = phash = tmp && BATcheckhash(tmp) &&
-                       (BATcount(tmp) == BATcount(b) ||
-                        BATcount(tmp) / ((size_t *) tmp->thash->heap.base)[5] 
* (s && !BATtdense(s) ? ilog2(BATcount(s)) : 1) < (s ? BATcount(s) : 
BATcount(b)) ||
-                        HASHget(tmp->thash, HASHprobe(tmp->thash, tl)) == 
HASHnil(tmp->thash));
-       }
        if (hash &&
            !phash && /* phash implies there is a hash table already */
            estimate == BUN_NONE &&
-           !BATcheckhash(b)) {
+           !b->thash) {
                /* no exact result size, but we need estimate to
                 * choose between hash- & scan-select (if we already
                 * have a hash, it's a no-brainer: we use it) */
@@ -1880,7 +1883,7 @@ BATselect(BAT *b, BAT *s, const void *tl
                                                  * (dbl) BATcount(b) * 1.1);
                        } else if (smpl_cnt > 0 && slct_cnt == 0) {
                                /* estimate low enough to trigger hash select */
-                               estimate = (BATcount(b) / 100) - 1;
+                               estimate = (cnt / 100) - 1;
                        }
                }
                hash = estimate < cnt / 100;
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to