diff options
author | Will Holley <willholley@gmail.com> | 2017-09-12 07:55:44 +0100 |
---|---|---|
committer | Will Holley <willholley@gmail.com> | 2017-09-12 13:06:40 +0100 |
commit | 04e4cfa0c670c89324887d9c1c28139cca65a230 (patch) | |
tree | 832b81a5d240f95cdd1f37520666cac7f176619c | |
parent | aa14e5d67650e5a484d5f4d862e17718b5b643eb (diff) | |
download | couchdb-04e4cfa0c670c89324887d9c1c28139cca65a230.tar.gz |
Avoid duplicate index selection in Mango
Previously, index selection for a given query
was run twice for each request - once to add
a warning in case a full database scan would be
performed and then again when the query was executed.
This moves the warning generation so that it occurs
at the end of the query processing and we can use
the existing index context to decide whether to
add a warning or not.
Whilst only a minor optimisation (which also assumes
we don't have cached query plans etc), it
at least moves index selection to where you'd expect
it to happen (query planning).
-rw-r--r-- | src/mango/src/mango_cursor.erl | 15 | ||||
-rw-r--r-- | src/mango/src/mango_cursor_text.erl | 3 | ||||
-rw-r--r-- | src/mango/src/mango_cursor_view.erl | 3 | ||||
-rw-r--r-- | src/mango/src/mango_httpd.erl | 16 | ||||
-rw-r--r-- | src/mango/test/12-use-correct-index.py | 7 |
5 files changed, 28 insertions, 16 deletions
diff --git a/src/mango/src/mango_cursor.erl b/src/mango/src/mango_cursor.erl index cf7179079..12ce2c93b 100644 --- a/src/mango/src/mango_cursor.erl +++ b/src/mango/src/mango_cursor.erl @@ -17,13 +17,15 @@ create/3, explain/1, execute/3, - maybe_filter_indexes/2 + maybe_filter_indexes/2, + maybe_add_warning/3 ]). -include_lib("couch/include/couch_db.hrl"). -include("mango.hrl"). -include("mango_cursor.hrl"). +-include("mango_idx.hrl"). -ifdef(HAVE_DREYFUS). @@ -134,3 +136,14 @@ group_indexes_by_type(Indexes) -> [] end end, ?CURSOR_MODULES). + + +maybe_add_warning(UserFun, #idx{type = IndexType}, UserAcc) -> + case IndexType of + <<"special">> -> + Arg = {add_key, warning, <<"no matching index found, create an index to optimize query time">>}, + {_Go, UserAcc0} = UserFun(Arg, UserAcc), + UserAcc0; + _ -> + UserAcc + end.
\ No newline at end of file diff --git a/src/mango/src/mango_cursor_text.erl b/src/mango/src/mango_cursor_text.erl index ea62cd68c..70c911ac1 100644 --- a/src/mango/src/mango_cursor_text.erl +++ b/src/mango/src/mango_cursor_text.erl @@ -124,7 +124,8 @@ execute(Cursor, UserFun, UserAcc) -> Arg = {add_key, bookmark, JsonBM}, {_Go, FinalUserAcc} = UserFun(Arg, LastUserAcc), FinalUserAcc0 = mango_execution_stats:maybe_add_stats(Opts, UserFun, Stats0, FinalUserAcc), - {ok, FinalUserAcc0} + FinalUserAcc1 = mango_cursor:maybe_add_warning(UserFun, Idx, FinalUserAcc0), + {ok, FinalUserAcc1} end. diff --git a/src/mango/src/mango_cursor_view.erl b/src/mango/src/mango_cursor_view.erl index b292704c3..31e198fca 100644 --- a/src/mango/src/mango_cursor_view.erl +++ b/src/mango/src/mango_cursor_view.erl @@ -118,7 +118,8 @@ execute(#cursor{db = Db, index = Idx, execution_stats = Stats} = Cursor0, UserFu {_Go, FinalUserAcc} = UserFun(Arg, LastCursor#cursor.user_acc), Stats0 = LastCursor#cursor.execution_stats, FinalUserAcc0 = mango_execution_stats:maybe_add_stats(Opts, UserFun, Stats0, FinalUserAcc), - {ok, FinalUserAcc0}; + FinalUserAcc1 = mango_cursor:maybe_add_warning(UserFun, Idx, FinalUserAcc0), + {ok, FinalUserAcc1}; {error, Reason} -> {error, Reason} end diff --git a/src/mango/src/mango_httpd.erl b/src/mango/src/mango_httpd.erl index a99b0544d..33e0c1c41 100644 --- a/src/mango/src/mango_httpd.erl +++ b/src/mango/src/mango_httpd.erl @@ -183,7 +183,7 @@ handle_find_req(#httpd{method='POST'}=Req, Db) -> chttpd:validate_ctype(Req, "application/json"), {ok, Opts0} = mango_opts:validate_find(chttpd:json_body_obj(Req)), {value, {selector, Sel}, Opts} = lists:keytake(selector, 1, Opts0), - {ok, Resp0} = start_find_resp(Req, Db, Sel, Opts), + {ok, Resp0} = start_find_resp(Req), {ok, AccOut} = run_find(Resp0, Db, Sel, Opts), end_find_resp(AccOut); @@ -230,18 +230,8 @@ convert_to_design_id(DDocId) -> end. -start_find_resp(Req, Db, Sel, Opts) -> - chttpd:start_delayed_json_response(Req, 200, [], maybe_add_warning(Db, Sel, Opts)). - - -maybe_add_warning(Db, Selector, Opts) -> - UsableIndexes = mango_idx:get_usable_indexes(Db, Selector, Opts), - case length(UsableIndexes) of - 0 -> - "{\"warning\":\"no matching index found, create an index to optimize query time\",\r\n\"docs\":["; - _ -> - "{\"docs\":[" - end. +start_find_resp(Req) -> + chttpd:start_delayed_json_response(Req, 200, [], "{\"docs\":["). end_find_resp(Acc0) -> diff --git a/src/mango/test/12-use-correct-index.py b/src/mango/test/12-use-correct-index.py index f1eaf5fe8..aaa798061 100644 --- a/src/mango/test/12-use-correct-index.py +++ b/src/mango/test/12-use-correct-index.py @@ -88,6 +88,13 @@ class ChooseCorrectIndexForDocs(mango.DbPerClass): explain = self.db.find({"name": "Eddie", "number": {"$lte": 12}}, explain=True) assert explain["index"]["ddoc"] == '_design/zzz' + def test_warn_on_full_db_scan(self): + selector = {"not_indexed":"foo"} + explain_resp = self.db.find(selector, explain=True, return_raw=True) + assert explain_resp["index"]["type"] == "special" + resp = self.db.find(selector, return_raw=True) + assert resp["warning"] == "no matching index found, create an index to optimize query time" + def test_chooses_idxA(self): DOCS2 = [ {"a":1, "b":1, "c":1}, |