ClickHouse

Форк
0
100 строк · 3.1 Кб
1
#include <Processors/QueryPlan/Optimizations/Optimizations.h>
2
#include <Processors/QueryPlan/ITransformingStep.h>
3
#include <Processors/QueryPlan/LimitStep.h>
4
#include <Processors/QueryPlan/TotalsHavingStep.h>
5
#include <Processors/QueryPlan/SortingStep.h>
6
#include <Processors/QueryPlan/WindowStep.h>
7
#include <Common/typeid_cast.h>
8

9
namespace DB::QueryPlanOptimizations
10
{
11

12
/// If plan looks like Limit -> Sorting, update limit for Sorting
13
static bool tryUpdateLimitForSortingSteps(QueryPlan::Node * node, size_t limit)
14
{
15
    if (limit == 0)
16
        return false;
17

18
    QueryPlanStepPtr & step = node->step;
19
    QueryPlan::Node * child = nullptr;
20
    bool updated = false;
21

22
    if (auto * sorting = typeid_cast<SortingStep *>(step.get()))
23
    {
24
        /// TODO: remove LimitStep here.
25
        sorting->updateLimit(limit);
26
        updated = true;
27
        child = node->children.front();
28
    }
29

30
    /// In case we have several sorting steps.
31
    /// Try update limit for them also if possible.
32
    if (child)
33
        tryUpdateLimitForSortingSteps(child, limit);
34

35
    return updated;
36
}
37

38
size_t tryPushDownLimit(QueryPlan::Node * parent_node, QueryPlan::Nodes &)
39
{
40
    if (parent_node->children.size() != 1)
41
        return 0;
42

43
    QueryPlan::Node * child_node = parent_node->children.front();
44

45
    auto & parent = parent_node->step;
46
    auto & child = child_node->step;
47
    auto * limit = typeid_cast<LimitStep *>(parent.get());
48

49
    if (!limit)
50
        return 0;
51

52
    /// Skip LIMIT WITH TIES by now.
53
    if (limit->withTies())
54
        return 0;
55

56
    const auto * transforming = dynamic_cast<const ITransformingStep *>(child.get());
57

58
    /// Skip everything which is not transform.
59
    if (!transforming)
60
        return 0;
61

62
    /// Special cases for sorting steps.
63
    if (tryUpdateLimitForSortingSteps(child_node, limit->getLimitForSorting()))
64
        return 0;
65

66
    /// Special case for TotalsHaving. Totals may be incorrect if we push down limit.
67
    if (typeid_cast<const TotalsHavingStep *>(child.get()))
68
        return 0;
69

70
    /// Disable for WindowStep.
71
    /// TODO: we can push down limit in some cases if increase the limit value.
72
    if (typeid_cast<const WindowStep *>(child.get()))
73
        return 0;
74

75
    /// Now we should decide if pushing down limit possible for this step.
76

77
    const auto & transform_traits = transforming->getTransformTraits();
78
    const auto & data_stream_traits = transforming->getDataStreamTraits();
79

80
    /// Cannot push down if child changes the number of rows.
81
    if (!transform_traits.preserves_number_of_rows)
82
        return 0;
83

84
    /// Cannot push down if data was sorted exactly by child stream.
85
    if (!child->getOutputStream().sort_description.empty() && !data_stream_traits.preserves_sorting)
86
        return 0;
87

88
    /// Now we push down limit only if it doesn't change any stream properties.
89
    /// TODO: some of them may be changed and, probably, not important for following streams. We may add such info.
90
    if (!limit->getOutputStream().hasEqualPropertiesWith(transforming->getOutputStream()))
91
        return 0;
92

93
    /// Input stream for Limit have changed.
94
    limit->updateInputStream(transforming->getInputStreams().front());
95

96
    parent.swap(child);
97
    return 2;
98
}
99

100
}
101

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.