summaryrefslogtreecommitdiff
path: root/jstests/sharding/covered_shard_key_indexes.js
blob: 43ba34ff882d6222c922e27577719aa43ce194a4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
//
// Tests that indexes containing the shard key can be used without fetching the document for
// particular queries
//

// Include helpers for analyzing explain output.
load("jstests/libs/analyze_plan.js");

var st = new ShardingTest({shards: 1});
st.stopBalancer();

var mongos = st.s0;
var admin = mongos.getDB("admin");
var shards = mongos.getCollection("config.shards").find().toArray();
var coll = mongos.getCollection("foo.bar");

//
//
// Tests with _id : 1 shard key

assert(admin.runCommand({enableSharding: coll.getDB() + ""}).ok);
printjson(admin.runCommand({movePrimary: coll.getDB() + "", to: shards[0]._id}));
assert(admin.runCommand({shardCollection: coll + "", key: {_id: 1}}).ok);
st.printShardingStatus();

// Insert some data
assert.writeOK(coll.insert({_id: true, a: true, b: true}));

assert.commandWorked(
    st.shard0.adminCommand({setParameter: 1, logComponentVerbosity: {query: {verbosity: 5}}}));

//
// Index without shard key query - not covered
assert.commandWorked(coll.ensureIndex({a: 1}));
assert.eq(1, coll.find({a: true}).explain(true).executionStats.totalDocsExamined);
assert.eq(1, coll.find({a: true}, {_id: 1, a: 1}).explain(true).executionStats.totalDocsExamined);

//
// Index with shard key query - covered when projecting
assert.commandWorked(coll.dropIndexes());
assert.commandWorked(coll.ensureIndex({a: 1, _id: 1}));
assert.eq(1, coll.find({a: true}).explain(true).executionStats.totalDocsExamined);
assert.eq(0, coll.find({a: true}, {_id: 1, a: 1}).explain(true).executionStats.totalDocsExamined);

//
// Compound index with shard key query - covered when projecting
assert.commandWorked(coll.dropIndexes());
assert.commandWorked(coll.ensureIndex({a: 1, b: 1, _id: 1}));
assert.eq(1, coll.find({a: true, b: true}).explain(true).executionStats.totalDocsExamined);
assert.eq(0,
          coll.find({a: true, b: true}, {_id: 1, a: 1})
              .explain(true)
              .executionStats.totalDocsExamined);

//
//
// Tests with _id : hashed shard key
coll.drop();
assert(admin.runCommand({shardCollection: coll + "", key: {_id: "hashed"}}).ok);
st.printShardingStatus();

// Insert some data
assert.writeOK(coll.insert({_id: true, a: true, b: true}));

//
// Index without shard key query - not covered
assert.commandWorked(coll.ensureIndex({a: 1}));
assert.eq(1, coll.find({a: true}).explain(true).executionStats.totalDocsExamined);
assert.eq(1, coll.find({a: true}, {_id: 0, a: 1}).explain(true).executionStats.totalDocsExamined);

//
// Index with shard key query - can't be covered since hashed index
assert.commandWorked(coll.dropIndex({a: 1}));
assert.eq(1, coll.find({_id: true}).explain(true).executionStats.totalDocsExamined);
assert.eq(1, coll.find({_id: true}, {_id: 0}).explain(true).executionStats.totalDocsExamined);

//
//
// Tests with compound shard key
coll.drop();
assert(admin.runCommand({shardCollection: coll + "", key: {a: 1, b: 1}}).ok);
st.printShardingStatus();

// Insert some data
assert.writeOK(coll.insert({_id: true, a: true, b: true, c: true, d: true}));

//
// Index without shard key query - not covered
assert.commandWorked(coll.ensureIndex({c: 1}));
assert.eq(1, coll.find({c: true}).explain(true).executionStats.totalDocsExamined);
assert.eq(1,
          coll.find({c: true}, {_id: 0, a: 1, b: 1, c: 1})
              .explain(true)
              .executionStats.totalDocsExamined);

//
// Index with shard key query - covered when projecting
assert.commandWorked(coll.dropIndex({c: 1}));
assert.commandWorked(coll.ensureIndex({c: 1, b: 1, a: 1}));
assert.eq(1, coll.find({c: true}).explain(true).executionStats.totalDocsExamined);
assert.eq(0,
          coll.find({c: true}, {_id: 0, a: 1, b: 1, c: 1})
              .explain(true)
              .executionStats.totalDocsExamined);

//
// Compound index with shard key query - covered when projecting
assert.commandWorked(coll.dropIndex({c: 1, b: 1, a: 1}));
assert.commandWorked(coll.ensureIndex({c: 1, d: 1, a: 1, b: 1, _id: 1}));
assert.eq(1, coll.find({c: true, d: true}).explain(true).executionStats.totalDocsExamined);
assert.eq(0,
          coll.find({c: true, d: true}, {a: 1, b: 1, c: 1, d: 1})
              .explain(true)
              .executionStats.totalDocsExamined);

//
//
// Tests with nested shard key
coll.drop();
assert(admin.runCommand({shardCollection: coll + "", key: {'a.b': 1}}).ok);
st.printShardingStatus();

// Insert some data
assert.writeOK(coll.insert({_id: true, a: {b: true}, c: true}));

//
// Index without shard key query - not covered
assert.commandWorked(coll.ensureIndex({c: 1}));
assert.eq(1, coll.find({c: true}).explain(true).executionStats.totalDocsExamined);
assert.eq(1,
          coll.find({c: true}, {_id: 0, 'a.b': 1, c: 1})
              .explain(true)
              .executionStats.totalDocsExamined);

//
// Index with shard key query - nested query not covered even when projecting
assert.commandWorked(coll.dropIndex({c: 1}));
assert.commandWorked(coll.ensureIndex({c: 1, 'a.b': 1}));
assert.eq(1, coll.find({c: true}).explain(true).executionStats.totalDocsExamined);
assert.eq(1,
          coll.find({c: true}, {_id: 0, 'a.b': 1, c: 1})
              .explain(true)
              .executionStats.totalDocsExamined);

//
//
// Tests with bad data with no shard key
coll.drop();
assert(admin.runCommand({shardCollection: coll + "", key: {a: 1}}).ok);
st.printShardingStatus();

// Insert some bad data manually
assert.writeOK(st.shard0.getCollection(coll.toString()).insert({_id: "bad data", c: true}));

//
// Index without shard key query - not covered but succeeds
assert.commandWorked(coll.ensureIndex({c: 1}));
var explain = coll.find({c: true}).explain(true).executionStats;
assert.eq(0, explain.nReturned);
assert.eq(1, explain.totalDocsExamined);
assert.eq(1, getChunkSkips(explain.executionStages.shards[0].executionStages));

//
// Index with shard key query - covered and succeeds and returns result
// NOTE: This is weird and only a result of the fact that we don't have a dedicated "does not exist"
// value for indexes
assert.commandWorked(coll.ensureIndex({c: 1, a: 1}));
jsTest.log(tojson(coll.find({c: true}, {_id: 0, a: 1, c: 1}).toArray()));
var explain = coll.find({c: true}, {_id: 0, a: 1, c: 1}).explain(true).executionStats;
assert.eq(1, explain.nReturned);
assert.eq(0, explain.totalDocsExamined);
assert.eq(0, getChunkSkips(explain.executionStages.shards[0].executionStages));

jsTest.log("DONE!");
st.stop();