@@ -293,66 +293,7 @@ func (m ShardMapper) mapVectorAggregationExpr(expr *syntax.VectorAggregationExpr
293
293
return nil , 0 , fmt .Errorf ("approx_topk is not enabled. See -limits.shard_aggregations" )
294
294
}
295
295
296
- // TODO(owen-d): integrate bounded sharding with approx_topk
297
- // I'm not doing this now because it uses a separate code path and may not handle
298
- // bounded shards in the same way
299
- shards , bytesPerShard , err := m .shards .Resolver ().Shards (expr )
300
- if err != nil {
301
- return nil , 0 , err
302
- }
303
-
304
- // approx_topk(k, inner) ->
305
- // topk(
306
- // k,
307
- // eval_cms(
308
- // __count_min_sketch__(inner, shard=1) ++ __count_min_sketch__(inner, shard=2)...
309
- // )
310
- // )
311
-
312
- countMinSketchExpr := syntax .MustClone (expr )
313
- countMinSketchExpr .Operation = syntax .OpTypeCountMinSketch
314
- countMinSketchExpr .Params = 0
315
-
316
- // Even if this query is not sharded the user wants an approximation. This is helpful if some
317
- // inferred label has a very high cardinality. Note that the querier does not support CountMinSketchEvalExpr
318
- // which is why it's evaluated on the front end.
319
- if shards == 0 {
320
- return & syntax.VectorAggregationExpr {
321
- Left : & CountMinSketchEvalExpr {
322
- downstreams : []DownstreamSampleExpr {{
323
- SampleExpr : countMinSketchExpr ,
324
- }},
325
- },
326
- Grouping : expr .Grouping ,
327
- Operation : syntax .OpTypeTopK ,
328
- Params : expr .Params ,
329
- }, bytesPerShard , nil
330
- }
331
-
332
- downstreams := make ([]DownstreamSampleExpr , 0 , shards )
333
- for shard := 0 ; shard < shards ; shard ++ {
334
- s := NewPowerOfTwoShard (index.ShardAnnotation {
335
- Shard : uint32 (shard ),
336
- Of : uint32 (shards ),
337
- })
338
- downstreams = append (downstreams , DownstreamSampleExpr {
339
- shard : & ShardWithChunkRefs {
340
- Shard : s ,
341
- },
342
- SampleExpr : countMinSketchExpr ,
343
- })
344
- }
345
-
346
- sharded := & CountMinSketchEvalExpr {
347
- downstreams : downstreams ,
348
- }
349
-
350
- return & syntax.VectorAggregationExpr {
351
- Left : sharded ,
352
- Grouping : expr .Grouping ,
353
- Operation : syntax .OpTypeTopK ,
354
- Params : expr .Params ,
355
- }, bytesPerShard , nil
296
+ return m .mapApproxTopk (expr , false )
356
297
default :
357
298
// this should not be reachable. If an operation is shardable it should
358
299
// have an optimization listed. Nonetheless, we log this as a warning
@@ -367,6 +308,16 @@ func (m ShardMapper) mapVectorAggregationExpr(expr *syntax.VectorAggregationExpr
367
308
}
368
309
return expr , exprStats .Bytes , nil
369
310
}
311
+ } else {
312
+ // if this AST contains unshardable operations, we still need to rewrite some operations (e.g. approx_topk) as if it had 0 shards as they are not supported on the querier
313
+ switch expr .Operation {
314
+ case syntax .OpTypeApproxTopK :
315
+ level .Error (util_log .Logger ).Log (
316
+ "msg" , "encountered unshardable approx_topk operation" ,
317
+ "operation" , expr .Operation ,
318
+ )
319
+ return m .mapApproxTopk (expr , true )
320
+ }
370
321
}
371
322
372
323
// if this AST contains unshardable operations, don't shard this at this level,
@@ -388,6 +339,69 @@ func (m ShardMapper) mapVectorAggregationExpr(expr *syntax.VectorAggregationExpr
388
339
}, bytesPerShard , nil
389
340
}
390
341
342
+ func (m ShardMapper ) mapApproxTopk (expr * syntax.VectorAggregationExpr , forceNoShard bool ) (* syntax.VectorAggregationExpr , uint64 , error ) {
343
+ // TODO(owen-d): integrate bounded sharding with approx_topk
344
+ // I'm not doing this now because it uses a separate code path and may not handle
345
+ // bounded shards in the same way
346
+ shards , bytesPerShard , err := m .shards .Resolver ().Shards (expr )
347
+ if err != nil {
348
+ return nil , 0 , err
349
+ }
350
+
351
+ // approx_topk(k, inner) ->
352
+ // topk(
353
+ // k,
354
+ // eval_cms(
355
+ // __count_min_sketch__(inner, shard=1) ++ __count_min_sketch__(inner, shard=2)...
356
+ // )
357
+ // )
358
+
359
+ countMinSketchExpr := syntax .MustClone (expr )
360
+ countMinSketchExpr .Operation = syntax .OpTypeCountMinSketch
361
+ countMinSketchExpr .Params = 0
362
+
363
+ // Even if this query is not sharded the user wants an approximation. This is helpful if some
364
+ // inferred label has a very high cardinality. Note that the querier does not support CountMinSketchEvalExpr
365
+ // which is why it's evaluated on the front end.
366
+ if shards == 0 || forceNoShard {
367
+ return & syntax.VectorAggregationExpr {
368
+ Left : & CountMinSketchEvalExpr {
369
+ downstreams : []DownstreamSampleExpr {{
370
+ SampleExpr : countMinSketchExpr ,
371
+ }},
372
+ },
373
+ Grouping : expr .Grouping ,
374
+ Operation : syntax .OpTypeTopK ,
375
+ Params : expr .Params ,
376
+ }, bytesPerShard , nil
377
+ }
378
+
379
+ downstreams := make ([]DownstreamSampleExpr , 0 , shards )
380
+ for shard := 0 ; shard < shards ; shard ++ {
381
+ s := NewPowerOfTwoShard (index.ShardAnnotation {
382
+ Shard : uint32 (shard ),
383
+ Of : uint32 (shards ),
384
+ })
385
+ downstreams = append (downstreams , DownstreamSampleExpr {
386
+ shard : & ShardWithChunkRefs {
387
+ Shard : s ,
388
+ },
389
+ SampleExpr : countMinSketchExpr ,
390
+ })
391
+ }
392
+
393
+ sharded := & CountMinSketchEvalExpr {
394
+ downstreams : downstreams ,
395
+ }
396
+
397
+ return & syntax.VectorAggregationExpr {
398
+ Left : sharded ,
399
+ Grouping : expr .Grouping ,
400
+ Operation : syntax .OpTypeTopK ,
401
+ Params : expr .Params ,
402
+ }, bytesPerShard , nil
403
+ }
404
+
391
405
func (m ShardMapper ) mapLabelReplaceExpr (expr * syntax.LabelReplaceExpr , r * downstreamRecorder , topLevel bool ) (syntax.SampleExpr , uint64 , error ) {
392
406
subMapped , bytesPerShard , err := m .Map (expr .Left , r , topLevel )
393
407
if err != nil {
0 commit comments