TOPN 查询是指下面这种 ORDER BY LIMIT 查询,在日志检索等明细查询场景中很常见,Doris 会自动对这种类型的查询进行优化。
1. SELECT * FROM tablex WHERE xxx ORDER BY c1,c2 ... LIMIT n
TOPN 查询优化的优化点
- 执行过程中动态对排序列构建范围过滤条件(比如 c1 >= 10000),读数据时自动带上前面的条件,利用 zonemap 索引过滤到一些数据甚至文件。
- 如果排序字段c1,c2 正好是table key的前缀,则更进一步优化,读数据的时候只用读数据文件的头部或者尾部n行。
- SELECT * 延迟物化,读数据和排序过程中只读排序列不读其它列,得到符合条件的行号后,再去读那n行需要的全部列数据,大幅减少读取和排序的列。
TOPN 查询优化的限制
- 只能用于 duplicate 表和 unique mow 表,因为 mor 表用这个优化可能有结果错误。
- 对于过大的n,优化内存消耗会很大,所以超过 topn_opt_limit_threshold session 变量的n 不会使用优化。
配置参数和查询分析
下面两个参数都是 session variable,可以针对某个 SQL 或者全局设置。
- topn_opt_limit_threshold,LIMIT n 小于这个值才会有优化,默认值1024,将它设置为 0 可以关闭 TOPN 查询优化。
- enable_two_phase_read_opt,是否开启优化3,默认为 true,可以调为 false 关闭这个优化。
检查 TOPN 查询优化是否启用
explain SQL 拿到 query plan 可以确认这个sql是否启用 TOPN 查询优化,以下面的为例:
- TOPN OPT 代表有优化1
- VOlapScanNode 下面有 SORT LIMIT 代表有优化2
- OPT TWO PHRASE 代表有优化3
1. 1:VTOP-N(137)
2. | order by: @timestamp18 DESC
3. | TOPN OPT
4. | OPT TWO PHASE
5. | offset: 0
6. | limit: 10
7. | distribute expr lists: applicationName5
8. |
9. 0:VOlapScanNode(106)
10. TABLE: log_db.log_core_all_no_index(log_core_all_no_index), PREAGGREGATION: ON
11. SORT INFO:
12. @timestamp18
13. SORT LIMIT: 10
14. TOPN OPT:1
15. PREDICATES: ZYCFC-TRACE-ID4 like '%flowId-1720055220933%'
16. partitions=1/8 (p20240704), tablets=250/250, tabletList=1727094,1727096,1727098 ...
17. cardinality=345472780, avgRowSize=0.0, numNodes=1
18. pushAggOp=NONE
检查 TOPN 查询优化执行时是否有效果
首先,可以将 topn_opt_limit_threshold 设置为 0 关闭 TOPN 查询优化,对比开启和关闭优化的 SQL 执行时间。
开启 TOPN查询优化后,在 query profile 中搜索 RuntimePredicate,关注下面几个指标:
- RowsZonemapRuntimePredicateFiltered 这个代表过滤掉的行数,越大越好
- NumSegmentFiltered 这个代表过滤掉的数据文件个数,越大越好
- BlockConditionsFilteredZonemapRuntimePredicateTime 代表过滤数据的耗时,越小越好
2.0.3 之前的版本RuntimePredicate的指标没有独立出来,可以通过Zonamap指标大致观察。
1. SegmentIterator:
2. - BitmapIndexFilterTimer: 46.54us
3. - BlockConditionsFilteredBloomFilterTime: 10.352us
4. - BlockConditionsFilteredDictTime: 7.299us
5. - BlockConditionsFilteredTime: 202.23ms
6. - BlockConditionsFilteredZonemapRuntimePredicateTime: 0ns
7. - BlockConditionsFilteredZonemapTime: 402.917ms
8. - BlockInitSeekCount: 399
9. - BlockInitSeekTime: 11.309ms
10. - BlockInitTime: 215.59ms
11. - BlockLoadTime: 7s567ms
12. - BlocksLoad: 392.97K (392970)
13. - CachedPagesNum: 0
14. - CollectIteratorMergeTime: 0ns
15. - CollectIteratorNormalTime: 0ns
16. - CompressedBytesRead: 29.76 MB
17. - DecompressorTimer: 427.713ms
18. - ExprFilterEvalTime: 3s930ms
19. - FirstReadSeekCount: 392.921K (392921)
20. - FirstReadSeekTime: 528.287ms
21. - FirstReadTime: 1s134ms
22. - IOTimer: 51.286ms
23. - InvertedIndexFilterTime: 49.457us
24. - InvertedIndexQueryBitmapCopyTime: 0ns
25. - InvertedIndexQueryBitmapOpTime: 0ns
26. - InvertedIndexQueryCacheHit: 0
27. - InvertedIndexQueryCacheMiss: 0
28. - InvertedIndexQueryTime: 0ns
29. - InvertedIndexSearcherOpenTime: 0ns
30. - InvertedIndexSearcherSearchTime: 0ns
31. - LazyReadSeekCount: 0
32. - LazyReadSeekTime: 0ns
33. - LazyReadTime: 106.952us
34. - NumSegmentFiltered: 0
35. - NumSegmentTotal: 50
36. - OutputColumnTime: 61.987ms
37. - OutputIndexResultColumnTimer: 12.345ms
38. - RawRowsRead: 3.929151M (3929151)
39. - RowsBitmapIndexFiltered: 0
40. - RowsBloomFilterFiltered: 0
41. - RowsConditionsFiltered: 6.38976M (6389760)
42. - RowsDictFiltered: 0
43. - RowsInvertedIndexFiltered: 0
44. - RowsKeyRangeFiltered: 0
45. - RowsShortCircuitPredFiltered: 0
46. - RowsShortCircuitPredInput: 0
47. - RowsStatsFiltered: 6.38976M (6389760)
48. - RowsVectorPredFiltered: 0
49. - RowsVectorPredInput: 0
50. - RowsZonemapRuntimePredicateFiltered: 6.38976M (6389760)
51. - SecondReadTime: 0ns
52. - ShortPredEvalTime: 0ns
53. - TotalPagesNum: 2.301K (2301)
54. - UncompressedBytesRead: 137.99 MB
55. - VectorPredEvalTime: 0ns
