summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWill Holley <willholley@gmail.com>2017-09-12 07:55:44 +0100
committerWill Holley <willholley@gmail.com>2017-09-12 13:06:40 +0100
commit04e4cfa0c670c89324887d9c1c28139cca65a230 (patch)
tree832b81a5d240f95cdd1f37520666cac7f176619c
parentaa14e5d67650e5a484d5f4d862e17718b5b643eb (diff)
downloadcouchdb-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.erl15
-rw-r--r--src/mango/src/mango_cursor_text.erl3
-rw-r--r--src/mango/src/mango_cursor_view.erl3
-rw-r--r--src/mango/src/mango_httpd.erl16
-rw-r--r--src/mango/test/12-use-correct-index.py7
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},