From 3e7e0a5d8f7d7b08b221715377c6e1579e75038f Mon Sep 17 00:00:00 2001 From: Radu Berinde Date: Thu, 11 Feb 2021 01:03:00 -0500 Subject: [PATCH] opt: prefer sorting fewer columns Currently, if we have to sort results and project a new column, there is no cost difference between the two orders and we happen to prefer the sort on top. It is preferable to sort before adding new columns to avoid storing the extra value in memory or on disk. This change improves the sort costing by adding a cost proportional to the total number of values. Fixes #32952. --- .../inverted_filter_json_array_dist | 20 +- .../opt/exec/execbuilder/testdata/distsql_agg | 13 +- .../execbuilder/testdata/distsql_numtables | 16 +- pkg/sql/opt/exec/execbuilder/testdata/explain | 8 +- .../testdata/inverted_filter_json_array | 16 +- .../exec/execbuilder/testdata/inverted_index | 16 +- pkg/sql/opt/exec/execbuilder/testdata/join | 85 ++- pkg/sql/opt/exec/execbuilder/testdata/orderby | 30 +- pkg/sql/opt/memo/testdata/format | 534 +++++++++--------- pkg/sql/opt/memo/testdata/memo | 22 +- pkg/sql/opt/memo/testdata/stats/inverted-geo | 12 +- pkg/sql/opt/norm/testdata/rules/ordering | 21 +- pkg/sql/opt/optbuilder/testdata/limit | 29 +- pkg/sql/opt/optbuilder/testdata/orderby | 81 ++- pkg/sql/opt/optgen/exprgen/testdata/explain | 4 +- pkg/sql/opt/optgen/exprgen/testdata/join | 10 +- pkg/sql/opt/optgen/exprgen/testdata/limit | 4 +- pkg/sql/opt/xform/coster.go | 9 +- pkg/sql/opt/xform/testdata/coster/join | 10 +- .../opt/xform/testdata/coster/perturb-cost | 2 +- pkg/sql/opt/xform/testdata/coster/sort | 14 +- pkg/sql/opt/xform/testdata/external/pgjdbc | 182 +++--- pkg/sql/opt/xform/testdata/external/tpce | 41 +- .../opt/xform/testdata/external/tpch-no-stats | 185 +++--- pkg/sql/opt/xform/testdata/physprops/ordering | 26 +- pkg/sql/opt/xform/testdata/rules/groupby | 94 +-- pkg/sql/opt/xform/testdata/rules/join | 14 +- pkg/sql/opt/xform/testdata/rules/join_order | 32 +- pkg/sql/opt/xform/testdata/rules/scan | 8 +- pkg/sql/opt/xform/testdata/rules/select | 13 +- 30 files changed, 769 insertions(+), 782 deletions(-) diff --git a/pkg/sql/logictest/testdata/logic_test/inverted_filter_json_array_dist b/pkg/sql/logictest/testdata/logic_test/inverted_filter_json_array_dist index 255b5f9d64ee..47ddc75e5cd2 100644 --- a/pkg/sql/logictest/testdata/logic_test/inverted_filter_json_array_dist +++ b/pkg/sql/logictest/testdata/logic_test/inverted_filter_json_array_dist @@ -171,11 +171,11 @@ vectorized: true • filter │ filter: (b @> '[[1, 2]]') OR (b @> '[[3, 4]]') │ -└── • sort - │ order: +a +└── • index join + │ table: json_tab@primary │ - └── • index join - │ table: json_tab@primary + └── • sort + │ order: +a │ └── • inverted filter │ inverted column: b_inverted_key @@ -186,7 +186,7 @@ vectorized: true table: json_tab@json_inv spans: 4 spans · -Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJyUk9Fv2j4Qx99_f8XpXkp_85Q4oarkp7RrqlExYAnSNkE0GXLrMlE7s03FhPjfpyS0W7oSwUMi350_d1_f6bZof65QYPx5MrwajKB3M0in6cfhOaTxMH43BQm3yfgD_LBafXVyAZ_ex0kMvQVE87XvhwRnsxlnEGTZ2TmMkxeRkEF_H7mJE7j-AhIZKp3TSD6QRTFDjhnD0uglWatN5drWFwb5BoXPsFDl2lXujOFSG0KxRVe4FaHAqVysKCGZk_F8ZJiTk8WqTvskOKoPhXpEhmkplRXgcd-7Mqb--NuW5U0MfSs2scpBqhwuQbvvZCwyHK-dgIizKMBsx1Cv3R9Z1sl7QsF37HjpA_VIxlF-W6wcGTIeb-t_iseb0oBWEHEBttIP1knjxBwv53Pf96tf-MqJ_1_9g8ZGIJWfgvA5Qt2B8J8OHHx-cMrz73Sh9oMLDgyuNMWDNL-O6314SvFUG0fGC9uFI_7mYPr-KemfR9pvF2j8AnpR8Mr2CCHu0vHoutmi9pX9Gj1fOWIaF6coTsiWWllq6T2U2d9lDCm_p2ZXrV6bJU2MXtZlGnNcc7UjJ-uaKG-MgWpClcC_Yd4JB91w0AmH3XDYCfe74X4nfPECznb__Q4AAP__3TS2RA== +Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJyUk9Fv2j4Qx99_f8XpXkp_85Q4oarkp7RrqlExYAnSNkE0GXLrMlE7s03FhPjfpyS0W7oSwUMi350_5-_5fFu0P1coMP48GV4NRtC7GaTT9OPwHNJ4GL-bgoTbZPwBflitvjq5gE_v4ySG3gKi-dr3Q4Kz2YwzCLLs7BzGyYtIyKC_j9zECVx_AYkMlc5pJB_Iopghx4xhafSSrNWmcm3rDYN8g8JnWKhy7Sp3xnCpDaHYoivcilDgVC5WlJDMyXg-MszJyWJVp30SHNWLQj0iw7SUygrwuO9dGVN__G3L8iaGvhWbWOUgVQ6XoN13MhYZjtdOQMRZFGC2Y6jX7o8s6-Q9oeA7drz0gXok4yi_LVaODBmPt_U_xeNNaUAriLgAW-kH66RxYo6X87nv-9UvfGXF_6_-QWMjkMpPQfgcob6B8J8bOFh-cEr5qTaOjBe0i474m4Ppw1PS3-lC7d9FeOBdlKZ4kObXca3tn3L4c0v77aMbv4BeFLwyPUKIu3Q8um6mqL1lP0bPW47oxsUpihOypVaWWnoPZfZ3GUPK76mZVavXZkkTo5f1MY05rrnakZN1TZQ3xkA1oUrg3zDvhINuOOiEw2447IT73XC_E754AWe7_34HAAD__4w7tkQ= # Combine predicates with OR. query T @@ -221,11 +221,11 @@ vectorized: true • filter │ filter: (b @> '[3]') OR (b @> '[[1, 2]]') │ -└── • sort - │ order: +a +└── • index join + │ table: json_tab@primary │ - └── • index join - │ table: json_tab@primary + └── • sort + │ order: +a │ └── • inverted filter │ inverted column: b_inverted_key @@ -236,7 +236,7 @@ vectorized: true table: json_tab@json_inv spans: 3 spans · -Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJyUU02P0zAQvfMrRnPZD4wSJ12QfMoumxVdlbYklQC1EXKbYQnq2sF2V0VV_ztKQgsBJdCLNV9v3huPZof22xoFxh-mo-vhGM5vh-ksfTe6gDQexa9ncAl3yeQtfLVafXJyCe_fxEkM50uIFhvfDwnO5mF2dgGTpB2ccwZB1mRu4wRuPoJEhkrnNJaPZFHMkWPGsDR6RdZqU4V2dcEw36LwGRaq3LgqnDFcaUModugKtyYUOJPLNSUkczKejwxzcrJY120PWqPaKNQTMkxLqawAj_vetTFe-OJoeVNDn4ttrHKQKocr0O4LGYsMJxsnIOIsCjDbM9Qb90uOdfKBUPA9-3_JQ_VExlF-V6wdGTIeb-s-5ONtaUAriLgAW-kG66RxYoGvFgvf96snPFr8snpfNj4CqfzfhXyBUE8b_DVt56jBKaPe60L9XE7QsZzSFI_SfG_9M4vCTv7wFP5UG0fGC9vcEX_e2X5wSvvjBgdtgiYu4DwK2vchhLhPJ-Ob5k5a2cOhHEs6JV6dIjEhW2plqSWwq7O_zxhS_kDNDVq9MSuaGr2qaRp3UuPqQE7WNVneOEPVpCqBv4N5LzjoBwe94LAfHPaCB_3gQS_46g9wtn_2IwAA___7DKoE +Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJyUk99v0zAQx9_5K073sh8YJU46kPyUjWWiU2lLUglQGyG3OUZQZwfbnYqq_u8oCS0ElEBfLN-Pz933dLod2m9rFBh_mI6uh2M4vx2ms_Td6ALSeBS_nsEl3CWTt_DVavXJySW8fxMnMZwvIVpsfD8kOJuH2dkFTJK2c84ZBFkTuY0TuPkIEhkqndNYPpJFMUeOGcPS6BVZq03l2tUJw3yLwmdYqHLjKnfGcKUNodihK9yaUOBMLteUkMzJeD4yzMnJYl2XPWiN6k-hnpBhWkplBXjc966N8cIXx583NfS52MYqB6lyuALtvpCxyHCycQIizqIAsz1DvXG_5FgnHwgF37P_lzxUT2Qc5XfF2pEh4_G27kM83pYGtIKIC7CVbrBOGicW-Gqx8H2_esLjj19W78vGRiCV_zuRLxDqaYO_pu0cNThl1FQbR8YL2gNG_Hln-fCU8ve6UD93H3bsvjTFozTfW2tkUdjZf3BK_-MGB-3ujV_AeRS070MIcZ9OxjfNnbSih0M5pnRKvDpFYkK21MpSS2BXZX-fMaT8gZobtHpjVjQ1elW3acxJzdWOnKxrorwxhqoJVQJ_h3kvHPTDQS8c9sNhLzzohwe98NUfcLZ_9iMAAP__ygWqBA== # More complex combination. query T diff --git a/pkg/sql/opt/exec/execbuilder/testdata/distsql_agg b/pkg/sql/opt/exec/execbuilder/testdata/distsql_agg index 63597f2ca729..2e346096b9cc 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/distsql_agg +++ b/pkg/sql/opt/exec/execbuilder/testdata/distsql_agg @@ -508,14 +508,13 @@ EXPLAIN (DISTSQL) SELECT c, d, sum(a+c::INT) + avg(b+d) FROM data GROUP BY c, d distribution: full vectorized: true · -• render +• sort +│ order: +c,+d │ -└── • group - │ group by: c, d - │ ordered: +c,+d +└── • render │ - └── • sort - │ order: +c,+d + └── • group + │ group by: c, d │ └── • render │ @@ -524,7 +523,7 @@ vectorized: true table: data@primary spans: FULL SCAN · -Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJzUl9tr60YQxt_7VyzzZKM18l6Ui56UnpMWg4-c2g70UExQrMUJJJa7UkpDyP9edEliyc2OzEZgv0mbfPpGM_P7kF8g_fsBfLj882p8MQpJ7_toNp_9Me6T2eX48tucLCmJKUmfHnsRccjS90fh_KxPHBL9s-rdEofEffLbdPKDxFEWkd-nk-sr8uvPQkYm0--X07c7oLBOYhVGjyoF_y9gQIEDBQEUJFDwYEFho5OlStNE5__yUghG8b_gDyncrzdPWX68oLBMtAL_BbL77EGBD_Po9kFNVRQr7Q6BQqyy6P6hsMnLCjb6_jHSz0BhtonWqU8GLiPROiaMJNmd0kBhqtax0j4JmBOI8i0pCbgTSEoCQUkgYfFKIXnKPspIs2ilwGevtH2ps0RnSrtevcpAODSQzqcWfB-Li9VKq1WUJdplw6YPDfJmT3SstIp98nZwEf68CSfzm_B6PO4For9zJPOj2fWPXsDer3h-9W1yHc6L63rxH_XcPpO7KL1rVMJowGHx-vGO4tN3_HhUUtbdfJRDA-6UDzM1o9n0ooTtZlQH9Tdnu83g7y0Q71dvDboZ5e3w-rWdylfpbY_cwPt0znKfOYfJINm4vDHiXVPHsLteJ02vKqv3-7MSTmolsPakszaku2zg8q5YR4qtWD-xYR2x2F5vdqyssw5Ybzb90FlH5lwRxb6Odd4eNN4KND5wRVegIcVWoJ3agIZYbO8WP1bQeAegNZt-6KAhc65A418HmmgPmmgFmhi4sivQkGIr0M5sQEMstndLHCtoogPQmk0_dNCQOVegia8DTbYHTbYCTQ5cryvQkGIr0M5tQEMstndLHitosgPQmk0_dNCQOVegyW5-Jv6P4VSlm2Sdqla__ob5NFS8UuUE0-RJL9WVTpaFTXk7KXTFQazSrPwrK29G6_JPeYHbYmYUc7OYN8VsWyxqYraf-NxGzKSV2sqbI97C2HBpbrg0ij2zs2ce9YnZ-sSoPjWLT43iM7P4zGbLzGJk0mYxtmWI2sob27JzcyYMkVAwRwqyZ8ycKQwJFbbDV10uEPkOYPusC6JGZoaosYXB5Hbu2Mowc7gwD-m7OV6wnTHHC0PyhZkDhiEJw6wiBlFjU7MLGUxu547ujDlnOJIz3CpnOPLtgn28mHOGIznDrXIGUWNfIHY5g8nt3LGd4eac4UjO8P1yZvH6y38BAAD__9PhRac= +Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJzUl9FvqkgUxt_3r5icJw1jcGbAWp6me293Y-LFrtpkbzamoTKxTVpwB9xs0_R_vwFqq1TnYMBE3wD78Z055_y-lFdI_n0CD67_vhleDXzS-j6YTCd_Ddtkcj28_jYlc0pCSpLVcysgFpl73sCf9tvEIsF_i9Y9sUjYJn-MRz9IGKQB-XM8ur0hv__MZWQ0_n49Xt8BhSgOlR88qwS8f4ABBQ4UBFBwgIILMwpLHc9VksQ6-5PXXDAI_wevS-ExWq7S7PGMwjzWCrxXSB_TJwUeTIP7JzVWQai03QUKoUqDx6fcJitLLvXjc6BfgMJkGUSJRzo2I0EUEkbi9EFpoDBWUai0RySzpChOSYnklnQokYIS6cDsjUK8Sj_LSNJgocBjb7R6qVeLhVaLII217W5XKgWVWSOu_J93_mh6598Ohy0p2l8eOdmjye2PlmQfVzy7-ja69af59Xapn-73L-QhSB5KxoxKDrO3zxPxvSf6fNUqinWotAq3Xpa_xXBm1t3lXT4h-3po_nFU8XG1bsTdIDu2294aYza99ehs6e6dnjhken7ciZc2K03uw1QU65J77zV0DjGcxDpV2ubltnGLSmEBhdEq9bKTZtvD9nq6FQa6a5wgmUUlt2DnXItucLe0AbtL6G2VwKoDzaoAbbOOzY-FNFLsxnr3zgRp1iTS7LSRRqb3jnSvOaQRwzXS5bbVQppX54lX4ol3bHEsnpBiN3br4kx44k3yxE-bJ2R67zxdNMcTYrjmqdy2WjyJ6jyJSjyJju0ciyek2I3d6p8JT6JJnsRp84RM752nfnM8IYZrnsptq8WTU50npxJPTsd2j8UTUuzGbl2eCU9Okzw5p80TMr13ni6b4wkxXPNUbltjn3A7PMcqWcZRoip9mXWzgatwoYrtSOKVnqsbHc9zm-J2lOvyB6FK0uJXVtwMouKnrMBNMSuL2aaYb4nZYeJ-HTETtdS1vDnizY0NF-aGC6PYMYsdo9g1l-0axbxntu4Z1Rdm8UWdLTOLkUmbxdiWIepa3tiW9Y0NvzQ3_NKcCV0kFMyRguwZ-0LXtjlHzL_gdVAkmdVYLpjVaCgh8nru2MIwc7QwJFuYOVyYi8jN8YLtjDleGJIvrFbAIGpsavUiBpPXc0d3xpwyDIkZZs4ZjuQMr5Uz3JwzHMkZXitnEDUyNUSN7Qwmr-eO_vtjzhmO5Aw35wxHcoYfljOzt99-BQAA__8WaCXH # There should be no "by hash" routers if there is a single stream. query T diff --git a/pkg/sql/opt/exec/execbuilder/testdata/distsql_numtables b/pkg/sql/opt/exec/execbuilder/testdata/distsql_numtables index 1f25b667ec6a..bf1515d7e578 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/distsql_numtables +++ b/pkg/sql/opt/exec/execbuilder/testdata/distsql_numtables @@ -51,17 +51,17 @@ EXPLAIN (DISTSQL) SELECT 5, 2+y, * FROM NumToStr WHERE y <= 10 ORDER BY str distribution: full vectorized: true · -• sort -│ order: +str +• render │ -└── • render +└── • sort + │ order: +str │ └── • scan missing stats table: numtostr@primary spans: [ - /10] · -Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJyUkFFL60AQhd_vrxjmvtxrR5KNFmRBiNqIgdrWJKCieYjJUAJpNu5uwFLy36UJYitU9PGcyfnysRs0rxVKDB4W04twBv8mYZzEd9P_EAfT4CqBMYEHI1gTHMF1NL-Ful1ZZayG-5sgCmANz63rnuTnIFyYR5MggstHMFYjYa0KnmUrNiifUGBK2GiVszFKb6tN_0FYvKF0Ccu6ae22TglzpRnlBm1pK0aJSfZSccRZwdpxkbBgm5VVj_3Q8RtdrjK9RsK4yWoj4dgRrvMXCSOuC9YSxlLKcJacEfhi5O0EAt_DtCNUrf2UMDZbMkrR0c9FY6Uta0fsO_qno4N47zf4iE2jasN7-ENkt0sJuVjy8NZGtTrnhVZ5_5shzvtdXxRs7HAVQwjr4bQV3B2Lb8fel3Ha_XkPAAD___kwwOA= +Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJyUkFFL-0AQxN__n2LZ_4valeQiBTkQojZioLY1CahoHmKylECai3cXsJR8d2mC2AoVfZzZm5kft0HzVqHE4HExvQxncDQJ4yS-nx5DHEyD6wTGBB6MYE1wAjfR_A7qdmWVsRoeboMogDW8tK57ll-AcGEeTYIIrp7AWI2EtSp4lq3YoHxGgSlho1XOxii9tTb9g7B4R-kSlnXT2q2dEuZKM8oN2tJWjBKT7LXiiLOCteMiYcE2K6u-9hPHb3S5yvQaCeMmq42EU0e4zn9MO0LV2q9yY7MloxQd_R4gVtqydsT-tu-NkDDiumAtYSylDGfJOYEvRt6OIPC9gxjeXzAiNo2qDe9hHGp2u5SQiyUPf21Uq3NeaJX3M4Oc97neKNjY4SoGEdbDaQu4GxY_hr1v4bT79xEAAP__JNjA3g== # Query which requires a full table scan. query T @@ -70,10 +70,10 @@ EXPLAIN (DISTSQL) SELECT 5, 2 + y, * FROM NumToStr WHERE y % 1000 = 0 ORDER BY s distribution: full vectorized: true · -• sort -│ order: +str +• render │ -└── • render +└── • sort + │ order: +str │ └── • filter │ filter: (y % 1000) = 0 @@ -83,7 +83,7 @@ vectorized: true table: numtostr@primary spans: FULL SCAN · -Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJzElV-LGjEUxd_7KcKFwm43MpP54-pAwbY7SwWr21FoS_Fh6lwWQSfTJEJF_O5lZtRdRZNUC76ZTM49x_wOZAXy9wwiiL8_9T50--TmoTscDb_2bskw7sWfRiSkxCN3ZEnJO_KYDL6QfDFXXCpBvn2Ok5jcLMlbwlzXvSXviUsGyUOckI8_iFQCKOQ8w346RwnRT2BAwQMKPlAIgEIIYwqF4BOUkovyyKoSdLM_ELkUpnmxUOX2mMKEC4RoBWqqZggRjNJfM0wwzVA4LlDIUKXTWWWzDdgpxHSeiiVQGBZpLiPScDzXdWG8psAX6mW4VOkzQsTW1D7A43SmUKBwwn33ej8iNx22uZgoirr9Uau6n81voJBgnpXnws0WJR12571aUNLxTkb1_iXqkAuFwmEH99QJ7k7O90_OfxnLRYYCs2NDj4To8wYvHLZ_W6fsgz17Zl8FZluFqgkNJ7DvgyHFrg_N6_fBEHXbB3ZuHzx7IJ41kKAC0rQHYkixA3J_fSCGqFsg3rlAfHsgvjWQZgWkZQ_EkGIHpHV9IIaoWyD-uUACeyCBNZASRcOShSHAjkX7-iwMUbcsgv_xeh2Zn6AseC7R6mFyy6cNs2esn0LJF2KCT4JPKpt6Oah01UaGUtVfWb3o5vWnMuBrMdOKPb3Y04r9PTE7FPv62E29daBVh3pxqBUbnJuX_Ol7rbild25pxW29uH1JbGbomKlk-pYxQ83YRT1jhqIFBnN905ihakzftcPs4_WbvwEAAP__8vsheA== +Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJy8lWGL2jAcxt_vU4Q_DO5mpE3aehoYuO16THB6q8I2hi86Gw5Bmy6JMBG_-2ir3ilnkiHdu2t7j8-v_T2QLajfS2AQf38cfhiM0M39YDKdfB3eokk8jD9NUYQRRS20wegdekjGX1C-XmmhtETfPsdJjG426C0ivu_fovfIR-PkPk7Qxx9IaQkYcpHxUbriCthPIICBAoYAMISAIYIZhkKKOVdKyPJftlVgkP0B5mNY5MVal7dnGOZCcmBb0Au95MBgmv5a8oSnGZeeDxgyrtPFsqo5APYLuVilcgMYJkWaK4baHvV9H2Y7DGKtn39c6fSJAyM77A7wsFhqLrn0otP2-j5DN32y_zCMscFo2q2-z_7viwj0XxAmQmouPXL2_n3aAgwJz7OSI9pXYtQnLfriAqM-vcgRXOR4rhcy45JnZ-VhC2a7V2BHoi0Kj5x-rUv14Uk9cZ8CcZ1CtYS2F7rvwUJx3EOnuT1YEA57IE3vgboLoc5CwkpIx12IheIo5K45IRaEgxDatJDAXUjgLKRTCem6C7FQHIV0mxNiQTgICZoWEroLCZ2FlCraji4sAEcXveZcWBAOLsL_eXq9wpFwVYhccaeDyS-PNp498fooVGIt5_xRinlVU1-Oq1x1I-NK109JfTHI60cl4MswMYapOUyN4eAkTM7DgRm7Y64OjenIHI6MYUtz55qXvjOGu-bmrjHcM4d712ATy8ZsIzOvjFhmRq7aGbEMLbSUm5dGLFMj5q2ds892b_4GAAD__4SNIW4= # Query with a restricted span + filter. query T diff --git a/pkg/sql/opt/exec/execbuilder/testdata/explain b/pkg/sql/opt/exec/execbuilder/testdata/explain index ebfe22ff0b90..37ebc2561542 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/explain +++ b/pkg/sql/opt/exec/execbuilder/testdata/explain @@ -1097,7 +1097,7 @@ EXPLAIN (OPT,VERBOSE) SELECT * FROM tc WHERE a = 10 ORDER BY b sort ├── columns: a:1 b:2 ├── stats: [rows=10, distinct(1)=1, null(1)=0] - ├── cost: 76.5943856 + ├── cost: 76.7943856 ├── fd: ()-->(1) ├── ordering: +2 opt(1) [actual: +2] ├── prune: (2) @@ -1123,7 +1123,7 @@ EXPLAIN (OPT,TYPES) SELECT * FROM tc WHERE a = 10 ORDER BY b sort ├── columns: a:1(int!null) b:2(int) ├── stats: [rows=10, distinct(1)=1, null(1)=0] - ├── cost: 76.5943856 + ├── cost: 76.7943856 ├── fd: ()-->(1) ├── ordering: +2 opt(1) [actual: +2] ├── prune: (2) @@ -1228,7 +1228,7 @@ sort ├── columns: a:1 b:2 [hidden: column6:6] ├── immutable ├── stats: [rows=333.333333] - ├── cost: 1183.26548 + ├── cost: 1193.26548 ├── fd: (1,2)-->(6) ├── ordering: +6 ├── prune: (1,2,6) @@ -1265,7 +1265,7 @@ sort ├── columns: a:1(int) b:2(int) [hidden: column6:6(int)] ├── immutable ├── stats: [rows=333.333333] - ├── cost: 1183.26548 + ├── cost: 1193.26548 ├── fd: (1,2)-->(6) ├── ordering: +6 ├── prune: (1,2,6) diff --git a/pkg/sql/opt/exec/execbuilder/testdata/inverted_filter_json_array b/pkg/sql/opt/exec/execbuilder/testdata/inverted_filter_json_array index f96dc796ac44..69fc790d2baf 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/inverted_filter_json_array +++ b/pkg/sql/opt/exec/execbuilder/testdata/inverted_filter_json_array @@ -102,11 +102,11 @@ vectorized: true • filter │ filter: (b @> '[[1, 2]]') OR (b @> '[[3, 4]]') │ -└── • sort - │ order: +a +└── • index join + │ table: json_tab@primary │ - └── • index join - │ table: json_tab@primary + └── • sort + │ order: +a │ └── • inverted filter │ inverted column: b_inverted_key @@ -146,11 +146,11 @@ vectorized: true • filter │ filter: (b @> '[3]') OR (b @> '[[1, 2]]') │ -└── • sort - │ order: +a +└── • index join + │ table: json_tab@primary │ - └── • index join - │ table: json_tab@primary + └── • sort + │ order: +a │ └── • inverted filter │ inverted column: b_inverted_key diff --git a/pkg/sql/opt/exec/execbuilder/testdata/inverted_index b/pkg/sql/opt/exec/execbuilder/testdata/inverted_index index 65b827493822..4aaa06c75554 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/inverted_index +++ b/pkg/sql/opt/exec/execbuilder/testdata/inverted_index @@ -419,11 +419,11 @@ EXPLAIN SELECT * from d where b @> '{"a": []}' ORDER BY a; distribution: local vectorized: true · -• sort -│ order: +a +• index join +│ table: d@primary │ -└── • index join - │ table: d@primary +└── • sort + │ order: +a │ └── • inverted filter │ inverted column: b_inverted_key @@ -440,11 +440,11 @@ EXPLAIN SELECT * from d where b @> '{"a": {}}' ORDER BY a; distribution: local vectorized: true · -• sort -│ order: +a +• index join +│ table: d@primary │ -└── • index join - │ table: d@primary +└── • sort + │ order: +a │ └── • inverted filter │ inverted column: b_inverted_key diff --git a/pkg/sql/opt/exec/execbuilder/testdata/join b/pkg/sql/opt/exec/execbuilder/testdata/join index 8bcc2a2debeb..269913971712 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/join +++ b/pkg/sql/opt/exec/execbuilder/testdata/join @@ -461,55 +461,52 @@ vectorized: true │ │ │ │ estimated row count: 354 (missing stats) │ │ │ │ pred: attnum = conkey[generate_series] │ │ │ │ - │ │ │ ├── • merge join (inner) + │ │ │ ├── • hash join (inner) │ │ │ │ │ columns: (attrelid, attname, attnum, oid, relname, relnamespace, oid, conname, contype, condeferrable, condeferred, conrelid, confrelid, confupdtype, confdeltype, conkey, confkey, oid, nspname) │ │ │ │ │ estimated row count: 107 (missing stats) - │ │ │ │ │ equality: (attrelid) = (oid) - │ │ │ │ │ merge ordering: +"(attrelid=oid)" + │ │ │ │ │ equality: (relnamespace) = (oid) │ │ │ │ │ - │ │ │ │ ├── • virtual table - │ │ │ │ │ columns: (attrelid, attname, attnum) - │ │ │ │ │ ordering: +attrelid - │ │ │ │ │ estimated row count: 1,000 (missing stats) - │ │ │ │ │ table: pg_attribute@pg_attribute_attrelid_idx + │ │ │ │ ├── • merge join (inner) + │ │ │ │ │ │ columns: (attrelid, attname, attnum, oid, relname, relnamespace, oid, conname, contype, condeferrable, condeferred, conrelid, confrelid, confupdtype, confdeltype, conkey, confkey) + │ │ │ │ │ │ estimated row count: 105 (missing stats) + │ │ │ │ │ │ equality: (attrelid) = (oid) + │ │ │ │ │ │ merge ordering: +"(attrelid=oid)" + │ │ │ │ │ │ + │ │ │ │ │ ├── • virtual table + │ │ │ │ │ │ columns: (attrelid, attname, attnum) + │ │ │ │ │ │ ordering: +attrelid + │ │ │ │ │ │ estimated row count: 1,000 (missing stats) + │ │ │ │ │ │ table: pg_attribute@pg_attribute_attrelid_idx + │ │ │ │ │ │ + │ │ │ │ │ └── • virtual table lookup join (inner) + │ │ │ │ │ │ columns: (oid, relname, relnamespace, oid, conname, contype, condeferrable, condeferred, conrelid, confrelid, confupdtype, confdeltype, conkey, confkey) + │ │ │ │ │ │ ordering: +oid + │ │ │ │ │ │ estimated row count: 10 (missing stats) + │ │ │ │ │ │ table: pg_constraint@pg_constraint_conrelid_idx + │ │ │ │ │ │ equality: (oid) = (conrelid) + │ │ │ │ │ │ pred: contype = 'f' + │ │ │ │ │ │ + │ │ │ │ │ └── • filter + │ │ │ │ │ │ columns: (oid, relname, relnamespace) + │ │ │ │ │ │ ordering: +oid + │ │ │ │ │ │ estimated row count: 10 (missing stats) + │ │ │ │ │ │ filter: relname = 'orders' + │ │ │ │ │ │ + │ │ │ │ │ └── • virtual table + │ │ │ │ │ columns: (oid, relname, relnamespace) + │ │ │ │ │ ordering: +oid + │ │ │ │ │ estimated row count: 1,000 (missing stats) + │ │ │ │ │ table: pg_class@pg_class_oid_idx │ │ │ │ │ - │ │ │ │ └── • sort - │ │ │ │ │ columns: (oid, relname, relnamespace, oid, conname, contype, condeferrable, condeferred, conrelid, confrelid, confupdtype, confdeltype, conkey, confkey, oid, nspname) - │ │ │ │ │ ordering: +oid - │ │ │ │ │ estimated row count: 11 (missing stats) - │ │ │ │ │ order: +oid + │ │ │ │ └── • filter + │ │ │ │ │ columns: (oid, nspname) + │ │ │ │ │ estimated row count: 10 (missing stats) + │ │ │ │ │ filter: nspname = 'public' │ │ │ │ │ - │ │ │ │ └── • hash join (inner) - │ │ │ │ │ columns: (oid, relname, relnamespace, oid, conname, contype, condeferrable, condeferred, conrelid, confrelid, confupdtype, confdeltype, conkey, confkey, oid, nspname) - │ │ │ │ │ estimated row count: 11 (missing stats) - │ │ │ │ │ equality: (relnamespace) = (oid) - │ │ │ │ │ - │ │ │ │ ├── • virtual table lookup join (inner) - │ │ │ │ │ │ columns: (oid, relname, relnamespace, oid, conname, contype, condeferrable, condeferred, conrelid, confrelid, confupdtype, confdeltype, conkey, confkey) - │ │ │ │ │ │ estimated row count: 10 (missing stats) - │ │ │ │ │ │ table: pg_constraint@pg_constraint_conrelid_idx - │ │ │ │ │ │ equality: (oid) = (conrelid) - │ │ │ │ │ │ pred: contype = 'f' - │ │ │ │ │ │ - │ │ │ │ │ └── • filter - │ │ │ │ │ │ columns: (oid, relname, relnamespace) - │ │ │ │ │ │ estimated row count: 10 (missing stats) - │ │ │ │ │ │ filter: relname = 'orders' - │ │ │ │ │ │ - │ │ │ │ │ └── • virtual table - │ │ │ │ │ columns: (oid, relname, relnamespace) - │ │ │ │ │ estimated row count: 1,000 (missing stats) - │ │ │ │ │ table: pg_class@primary - │ │ │ │ │ - │ │ │ │ └── • filter - │ │ │ │ │ columns: (oid, nspname) - │ │ │ │ │ estimated row count: 10 (missing stats) - │ │ │ │ │ filter: nspname = 'public' - │ │ │ │ │ - │ │ │ │ └── • virtual table - │ │ │ │ columns: (oid, nspname) - │ │ │ │ estimated row count: 1,000 (missing stats) - │ │ │ │ table: pg_namespace@primary + │ │ │ │ └── • virtual table + │ │ │ │ columns: (oid, nspname) + │ │ │ │ estimated row count: 1,000 (missing stats) + │ │ │ │ table: pg_namespace@primary │ │ │ │ │ │ │ └── • project set │ │ │ │ columns: (generate_series) diff --git a/pkg/sql/opt/exec/execbuilder/testdata/orderby b/pkg/sql/opt/exec/execbuilder/testdata/orderby index fa6b64e4d1a9..4dd899ebb3d8 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/orderby +++ b/pkg/sql/opt/exec/execbuilder/testdata/orderby @@ -858,18 +858,19 @@ vectorized: true • project │ columns: (b, a) │ -└── • sort +└── • render │ columns: (column6, a, b) │ ordering: +a │ estimated row count: 1,000 (missing stats) - │ order: +a + │ render column6: a + │ render a: a + │ render b: b │ - └── • render - │ columns: (column6, a, b) + └── • sort + │ columns: (a, b) + │ ordering: +a │ estimated row count: 1,000 (missing stats) - │ render column6: a - │ render a: a - │ render b: b + │ order: +a │ └── • scan columns: (a, b) @@ -886,18 +887,19 @@ vectorized: true • project │ columns: (b, a) │ -└── • sort +└── • render │ columns: (column6, a, b) │ ordering: +b │ estimated row count: 1,000 (missing stats) - │ order: +b + │ render column6: b + │ render a: a + │ render b: b │ - └── • render - │ columns: (column6, a, b) + └── • sort + │ columns: (a, b) + │ ordering: +b │ estimated row count: 1,000 (missing stats) - │ render column6: b - │ render a: a - │ render b: b + │ order: +b │ └── • scan columns: (a, b) diff --git a/pkg/sql/opt/memo/testdata/format b/pkg/sql/opt/memo/testdata/format index 7d41423be9e5..e231e19b97da 100644 --- a/pkg/sql/opt/memo/testdata/format +++ b/pkg/sql/opt/memo/testdata/format @@ -5,333 +5,339 @@ CREATE TABLE t (a INT, b INT, k INT PRIMARY KEY) opt format=show-all SELECT a + 1, min(b) FROM t WHERE k + a > b GROUP BY a ORDER BY a ---- -sort +project ├── columns: "?column?":6(int) min:5(int!null) [hidden: t.public.t.a:1(int)] ├── immutable ├── stats: [rows=98.1771622] - ├── cost: 1101.88224 + ├── cost: 1103.84579 ├── key: (1) ├── fd: (1)-->(5,6) ├── ordering: +1 ├── prune: (1,5,6) - └── project - ├── columns: "?column?":6(int) t.public.t.a:1(int) min:5(int!null) - ├── immutable - ├── stats: [rows=98.1771622] - ├── cost: 1086.91531 - ├── key: (1) - ├── fd: (1)-->(5,6) - ├── prune: (1,5,6) - ├── group-by - │ ├── columns: t.public.t.a:1(int) min:5(int!null) - │ ├── grouping columns: t.public.t.a:1(int) - │ ├── immutable - │ ├── stats: [rows=98.1771622, distinct(1)=98.1771622, null(1)=1] - │ ├── cost: 1084.94177 - │ ├── key: (1) - │ ├── fd: (1)-->(5) - │ ├── prune: (5) - │ ├── select - │ │ ├── columns: t.public.t.a:1(int) t.public.t.b:2(int!null) t.public.t.k:3(int!null) - │ │ ├── immutable - │ │ ├── stats: [rows=330, distinct(1)=98.1771622, null(1)=3.3, distinct(2)=100, null(2)=0] - │ │ ├── cost: 1074.04 - │ │ ├── key: (3) - │ │ ├── fd: (3)-->(1,2) - │ │ ├── interesting orderings: (+3) - │ │ ├── scan t.public.t - │ │ │ ├── columns: t.public.t.a:1(int) t.public.t.b:2(int) t.public.t.k:3(int!null) - │ │ │ ├── stats: [rows=1000, distinct(1)=100, null(1)=10, distinct(2)=100, null(2)=10] - │ │ │ ├── cost: 1064.02 - │ │ │ ├── key: (3) - │ │ │ ├── fd: (3)-->(1,2) - │ │ │ ├── prune: (1-3) - │ │ │ └── interesting orderings: (+3) - │ │ └── filters - │ │ └── lt [type=bool, outer=(1-3), immutable, constraints=(/2: (/NULL - ])] - │ │ ├── variable: t.public.t.b:2 [type=int] - │ │ └── plus [type=int] - │ │ ├── variable: t.public.t.k:3 [type=int] - │ │ └── variable: t.public.t.a:1 [type=int] - │ └── aggregations - │ └── min [as=min:5, type=int, outer=(2)] - │ └── variable: t.public.t.b:2 [type=int] - └── projections - └── plus [as="?column?":6, type=int, outer=(1), immutable] - ├── variable: t.public.t.a:1 [type=int] - └── const: 1 [type=int] + ├── sort + │ ├── columns: t.public.t.a:1(int) min:5(int!null) + │ ├── immutable + │ ├── stats: [rows=98.1771622, distinct(1)=98.1771622, null(1)=1] + │ ├── cost: 1101.87224 + │ ├── key: (1) + │ ├── fd: (1)-->(5) + │ ├── ordering: +1 + │ ├── prune: (5) + │ └── group-by + │ ├── columns: t.public.t.a:1(int) min:5(int!null) + │ ├── grouping columns: t.public.t.a:1(int) + │ ├── immutable + │ ├── stats: [rows=98.1771622, distinct(1)=98.1771622, null(1)=1] + │ ├── cost: 1084.94177 + │ ├── key: (1) + │ ├── fd: (1)-->(5) + │ ├── prune: (5) + │ ├── select + │ │ ├── columns: t.public.t.a:1(int) t.public.t.b:2(int!null) t.public.t.k:3(int!null) + │ │ ├── immutable + │ │ ├── stats: [rows=330, distinct(1)=98.1771622, null(1)=3.3, distinct(2)=100, null(2)=0] + │ │ ├── cost: 1074.04 + │ │ ├── key: (3) + │ │ ├── fd: (3)-->(1,2) + │ │ ├── interesting orderings: (+3) + │ │ ├── scan t.public.t + │ │ │ ├── columns: t.public.t.a:1(int) t.public.t.b:2(int) t.public.t.k:3(int!null) + │ │ │ ├── stats: [rows=1000, distinct(1)=100, null(1)=10, distinct(2)=100, null(2)=10] + │ │ │ ├── cost: 1064.02 + │ │ │ ├── key: (3) + │ │ │ ├── fd: (3)-->(1,2) + │ │ │ ├── prune: (1-3) + │ │ │ └── interesting orderings: (+3) + │ │ └── filters + │ │ └── lt [type=bool, outer=(1-3), immutable, constraints=(/2: (/NULL - ])] + │ │ ├── variable: t.public.t.b:2 [type=int] + │ │ └── plus [type=int] + │ │ ├── variable: t.public.t.k:3 [type=int] + │ │ └── variable: t.public.t.a:1 [type=int] + │ └── aggregations + │ └── min [as=min:5, type=int, outer=(2)] + │ └── variable: t.public.t.b:2 [type=int] + └── projections + └── plus [as="?column?":6, type=int, outer=(1), immutable] + ├── variable: t.public.t.a:1 [type=int] + └── const: 1 [type=int] opt format=(hide-miscprops,hide-constraints,hide-funcdeps,hide-ruleprops) SELECT a + 1, min(b) FROM t WHERE k + a > b GROUP BY a ORDER BY a ---- -sort +project ├── columns: "?column?":6(int) min:5(int!null) [hidden: t.public.t.a:1(int)] ├── stats: [rows=98.1771622] - ├── cost: 1101.88224 + ├── cost: 1103.84579 ├── ordering: +1 - └── project - ├── columns: "?column?":6(int) t.public.t.a:1(int) min:5(int!null) - ├── stats: [rows=98.1771622] - ├── cost: 1086.91531 - ├── group-by - │ ├── columns: t.public.t.a:1(int) min:5(int!null) - │ ├── grouping columns: t.public.t.a:1(int) - │ ├── stats: [rows=98.1771622, distinct(1)=98.1771622, null(1)=1] - │ ├── cost: 1084.94177 - │ ├── select - │ │ ├── columns: t.public.t.a:1(int) t.public.t.b:2(int!null) t.public.t.k:3(int!null) - │ │ ├── stats: [rows=330, distinct(1)=98.1771622, null(1)=3.3, distinct(2)=100, null(2)=0] - │ │ ├── cost: 1074.04 - │ │ ├── scan t.public.t - │ │ │ ├── columns: t.public.t.a:1(int) t.public.t.b:2(int) t.public.t.k:3(int!null) - │ │ │ ├── stats: [rows=1000, distinct(1)=100, null(1)=10, distinct(2)=100, null(2)=10] - │ │ │ └── cost: 1064.02 - │ │ └── filters - │ │ └── lt [type=bool] - │ │ ├── variable: t.public.t.b:2 [type=int] - │ │ └── plus [type=int] - │ │ ├── variable: t.public.t.k:3 [type=int] - │ │ └── variable: t.public.t.a:1 [type=int] - │ └── aggregations - │ └── min [as=min:5, type=int] - │ └── variable: t.public.t.b:2 [type=int] - └── projections - └── plus [as="?column?":6, type=int] - ├── variable: t.public.t.a:1 [type=int] - └── const: 1 [type=int] + ├── sort + │ ├── columns: t.public.t.a:1(int) min:5(int!null) + │ ├── stats: [rows=98.1771622, distinct(1)=98.1771622, null(1)=1] + │ ├── cost: 1101.87224 + │ ├── ordering: +1 + │ └── group-by + │ ├── columns: t.public.t.a:1(int) min:5(int!null) + │ ├── grouping columns: t.public.t.a:1(int) + │ ├── stats: [rows=98.1771622, distinct(1)=98.1771622, null(1)=1] + │ ├── cost: 1084.94177 + │ ├── select + │ │ ├── columns: t.public.t.a:1(int) t.public.t.b:2(int!null) t.public.t.k:3(int!null) + │ │ ├── stats: [rows=330, distinct(1)=98.1771622, null(1)=3.3, distinct(2)=100, null(2)=0] + │ │ ├── cost: 1074.04 + │ │ ├── scan t.public.t + │ │ │ ├── columns: t.public.t.a:1(int) t.public.t.b:2(int) t.public.t.k:3(int!null) + │ │ │ ├── stats: [rows=1000, distinct(1)=100, null(1)=10, distinct(2)=100, null(2)=10] + │ │ │ └── cost: 1064.02 + │ │ └── filters + │ │ └── lt [type=bool] + │ │ ├── variable: t.public.t.b:2 [type=int] + │ │ └── plus [type=int] + │ │ ├── variable: t.public.t.k:3 [type=int] + │ │ └── variable: t.public.t.a:1 [type=int] + │ └── aggregations + │ └── min [as=min:5, type=int] + │ └── variable: t.public.t.b:2 [type=int] + └── projections + └── plus [as="?column?":6, type=int] + ├── variable: t.public.t.a:1 [type=int] + └── const: 1 [type=int] opt format=(hide-stats,hide-cost,hide-qual,hide-scalars) SELECT a + 1, min(b) FROM t WHERE k + a > b GROUP BY a ORDER BY a ---- -sort +project ├── columns: "?column?":6(int) min:5(int!null) [hidden: a:1(int)] ├── immutable ├── key: (1) ├── fd: (1)-->(5,6) ├── ordering: +1 ├── prune: (1,5,6) - └── project - ├── columns: "?column?":6(int) a:1(int) min:5(int!null) - ├── immutable - ├── key: (1) - ├── fd: (1)-->(5,6) - ├── prune: (1,5,6) - ├── group-by - │ ├── columns: a:1(int) min:5(int!null) - │ ├── grouping columns: a:1(int) - │ ├── immutable - │ ├── key: (1) - │ ├── fd: (1)-->(5) - │ ├── prune: (5) - │ ├── select - │ │ ├── columns: a:1(int) b:2(int!null) k:3(int!null) - │ │ ├── immutable - │ │ ├── key: (3) - │ │ ├── fd: (3)-->(1,2) - │ │ ├── interesting orderings: (+3) - │ │ ├── scan t - │ │ │ ├── columns: a:1(int) b:2(int) k:3(int!null) - │ │ │ ├── key: (3) - │ │ │ ├── fd: (3)-->(1,2) - │ │ │ ├── prune: (1-3) - │ │ │ └── interesting orderings: (+3) - │ │ └── filters - │ │ └── b:2 < (k:3 + a:1) [type=bool, outer=(1-3), immutable, constraints=(/2: (/NULL - ])] - │ └── aggregations - │ └── min [as=min:5, type=int, outer=(2)] - │ └── b:2 [type=int] - └── projections - └── a:1 + 1 [as="?column?":6, type=int, outer=(1), immutable] + ├── sort + │ ├── columns: a:1(int) min:5(int!null) + │ ├── immutable + │ ├── key: (1) + │ ├── fd: (1)-->(5) + │ ├── ordering: +1 + │ ├── prune: (5) + │ └── group-by + │ ├── columns: a:1(int) min:5(int!null) + │ ├── grouping columns: a:1(int) + │ ├── immutable + │ ├── key: (1) + │ ├── fd: (1)-->(5) + │ ├── prune: (5) + │ ├── select + │ │ ├── columns: a:1(int) b:2(int!null) k:3(int!null) + │ │ ├── immutable + │ │ ├── key: (3) + │ │ ├── fd: (3)-->(1,2) + │ │ ├── interesting orderings: (+3) + │ │ ├── scan t + │ │ │ ├── columns: a:1(int) b:2(int) k:3(int!null) + │ │ │ ├── key: (3) + │ │ │ ├── fd: (3)-->(1,2) + │ │ │ ├── prune: (1-3) + │ │ │ └── interesting orderings: (+3) + │ │ └── filters + │ │ └── b:2 < (k:3 + a:1) [type=bool, outer=(1-3), immutable, constraints=(/2: (/NULL - ])] + │ └── aggregations + │ └── min [as=min:5, type=int, outer=(2)] + │ └── b:2 [type=int] + └── projections + └── a:1 + 1 [as="?column?":6, type=int, outer=(1), immutable] opt format=(hide-stats,hide-cost,hide-qual,hide-scalars,hide-types) SELECT a + 1, min(b) FROM t WHERE k + a > b GROUP BY a ORDER BY a ---- -sort +project ├── columns: "?column?":6 min:5!null [hidden: a:1] ├── immutable ├── key: (1) ├── fd: (1)-->(5,6) ├── ordering: +1 ├── prune: (1,5,6) - └── project - ├── columns: "?column?":6 a:1 min:5!null - ├── immutable - ├── key: (1) - ├── fd: (1)-->(5,6) - ├── prune: (1,5,6) - ├── group-by - │ ├── columns: a:1 min:5!null - │ ├── grouping columns: a:1 - │ ├── immutable - │ ├── key: (1) - │ ├── fd: (1)-->(5) - │ ├── prune: (5) - │ ├── select - │ │ ├── columns: a:1 b:2!null k:3!null - │ │ ├── immutable - │ │ ├── key: (3) - │ │ ├── fd: (3)-->(1,2) - │ │ ├── interesting orderings: (+3) - │ │ ├── scan t - │ │ │ ├── columns: a:1 b:2 k:3!null - │ │ │ ├── key: (3) - │ │ │ ├── fd: (3)-->(1,2) - │ │ │ ├── prune: (1-3) - │ │ │ └── interesting orderings: (+3) - │ │ └── filters - │ │ └── b:2 < (k:3 + a:1) [outer=(1-3), immutable, constraints=(/2: (/NULL - ])] - │ └── aggregations - │ └── min [as=min:5, outer=(2)] - │ └── b:2 - └── projections - └── a:1 + 1 [as="?column?":6, outer=(1), immutable] + ├── sort + │ ├── columns: a:1 min:5!null + │ ├── immutable + │ ├── key: (1) + │ ├── fd: (1)-->(5) + │ ├── ordering: +1 + │ ├── prune: (5) + │ └── group-by + │ ├── columns: a:1 min:5!null + │ ├── grouping columns: a:1 + │ ├── immutable + │ ├── key: (1) + │ ├── fd: (1)-->(5) + │ ├── prune: (5) + │ ├── select + │ │ ├── columns: a:1 b:2!null k:3!null + │ │ ├── immutable + │ │ ├── key: (3) + │ │ ├── fd: (3)-->(1,2) + │ │ ├── interesting orderings: (+3) + │ │ ├── scan t + │ │ │ ├── columns: a:1 b:2 k:3!null + │ │ │ ├── key: (3) + │ │ │ ├── fd: (3)-->(1,2) + │ │ │ ├── prune: (1-3) + │ │ │ └── interesting orderings: (+3) + │ │ └── filters + │ │ └── b:2 < (k:3 + a:1) [outer=(1-3), immutable, constraints=(/2: (/NULL - ])] + │ └── aggregations + │ └── min [as=min:5, outer=(2)] + │ └── b:2 + └── projections + └── a:1 + 1 [as="?column?":6, outer=(1), immutable] opt format=(hide-stats,hide-cost,hide-qual,hide-scalars,hide-notnull) SELECT a + 1, min(b) FROM t WHERE k + a > b GROUP BY a ORDER BY a ---- -sort +project ├── columns: "?column?":6(int) min:5(int) [hidden: a:1(int)] ├── immutable ├── key: (1) ├── fd: (1)-->(5,6) ├── ordering: +1 ├── prune: (1,5,6) - └── project - ├── columns: "?column?":6(int) a:1(int) min:5(int) - ├── immutable - ├── key: (1) - ├── fd: (1)-->(5,6) - ├── prune: (1,5,6) - ├── group-by - │ ├── columns: a:1(int) min:5(int) - │ ├── grouping columns: a:1(int) - │ ├── immutable - │ ├── key: (1) - │ ├── fd: (1)-->(5) - │ ├── prune: (5) - │ ├── select - │ │ ├── columns: a:1(int) b:2(int) k:3(int) - │ │ ├── immutable - │ │ ├── key: (3) - │ │ ├── fd: (3)-->(1,2) - │ │ ├── interesting orderings: (+3) - │ │ ├── scan t - │ │ │ ├── columns: a:1(int) b:2(int) k:3(int) - │ │ │ ├── key: (3) - │ │ │ ├── fd: (3)-->(1,2) - │ │ │ ├── prune: (1-3) - │ │ │ └── interesting orderings: (+3) - │ │ └── filters - │ │ └── b:2 < (k:3 + a:1) [type=bool, outer=(1-3), immutable, constraints=(/2: (/NULL - ])] - │ └── aggregations - │ └── min [as=min:5, type=int, outer=(2)] - │ └── b:2 [type=int] - └── projections - └── a:1 + 1 [as="?column?":6, type=int, outer=(1), immutable] + ├── sort + │ ├── columns: a:1(int) min:5(int) + │ ├── immutable + │ ├── key: (1) + │ ├── fd: (1)-->(5) + │ ├── ordering: +1 + │ ├── prune: (5) + │ └── group-by + │ ├── columns: a:1(int) min:5(int) + │ ├── grouping columns: a:1(int) + │ ├── immutable + │ ├── key: (1) + │ ├── fd: (1)-->(5) + │ ├── prune: (5) + │ ├── select + │ │ ├── columns: a:1(int) b:2(int) k:3(int) + │ │ ├── immutable + │ │ ├── key: (3) + │ │ ├── fd: (3)-->(1,2) + │ │ ├── interesting orderings: (+3) + │ │ ├── scan t + │ │ │ ├── columns: a:1(int) b:2(int) k:3(int) + │ │ │ ├── key: (3) + │ │ │ ├── fd: (3)-->(1,2) + │ │ │ ├── prune: (1-3) + │ │ │ └── interesting orderings: (+3) + │ │ └── filters + │ │ └── b:2 < (k:3 + a:1) [type=bool, outer=(1-3), immutable, constraints=(/2: (/NULL - ])] + │ └── aggregations + │ └── min [as=min:5, type=int, outer=(2)] + │ └── b:2 [type=int] + └── projections + └── a:1 + 1 [as="?column?":6, type=int, outer=(1), immutable] opt format=(hide-stats,hide-cost,hide-qual,hide-scalars,hide-types,hide-notnull) SELECT a + 1, min(b) FROM t WHERE k + a > b GROUP BY a ORDER BY a ---- -sort +project ├── columns: "?column?":6 min:5 [hidden: a:1] ├── immutable ├── key: (1) ├── fd: (1)-->(5,6) ├── ordering: +1 ├── prune: (1,5,6) - └── project - ├── columns: "?column?":6 a:1 min:5 - ├── immutable - ├── key: (1) - ├── fd: (1)-->(5,6) - ├── prune: (1,5,6) - ├── group-by - │ ├── columns: a:1 min:5 - │ ├── grouping columns: a:1 - │ ├── immutable - │ ├── key: (1) - │ ├── fd: (1)-->(5) - │ ├── prune: (5) - │ ├── select - │ │ ├── columns: a:1 b:2 k:3 - │ │ ├── immutable - │ │ ├── key: (3) - │ │ ├── fd: (3)-->(1,2) - │ │ ├── interesting orderings: (+3) - │ │ ├── scan t - │ │ │ ├── columns: a:1 b:2 k:3 - │ │ │ ├── key: (3) - │ │ │ ├── fd: (3)-->(1,2) - │ │ │ ├── prune: (1-3) - │ │ │ └── interesting orderings: (+3) - │ │ └── filters - │ │ └── b:2 < (k:3 + a:1) [outer=(1-3), immutable, constraints=(/2: (/NULL - ])] - │ └── aggregations - │ └── min [as=min:5, outer=(2)] - │ └── b:2 - └── projections - └── a:1 + 1 [as="?column?":6, outer=(1), immutable] + ├── sort + │ ├── columns: a:1 min:5 + │ ├── immutable + │ ├── key: (1) + │ ├── fd: (1)-->(5) + │ ├── ordering: +1 + │ ├── prune: (5) + │ └── group-by + │ ├── columns: a:1 min:5 + │ ├── grouping columns: a:1 + │ ├── immutable + │ ├── key: (1) + │ ├── fd: (1)-->(5) + │ ├── prune: (5) + │ ├── select + │ │ ├── columns: a:1 b:2 k:3 + │ │ ├── immutable + │ │ ├── key: (3) + │ │ ├── fd: (3)-->(1,2) + │ │ ├── interesting orderings: (+3) + │ │ ├── scan t + │ │ │ ├── columns: a:1 b:2 k:3 + │ │ │ ├── key: (3) + │ │ │ ├── fd: (3)-->(1,2) + │ │ │ ├── prune: (1-3) + │ │ │ └── interesting orderings: (+3) + │ │ └── filters + │ │ └── b:2 < (k:3 + a:1) [outer=(1-3), immutable, constraints=(/2: (/NULL - ])] + │ └── aggregations + │ └── min [as=min:5, outer=(2)] + │ └── b:2 + └── projections + └── a:1 + 1 [as="?column?":6, outer=(1), immutable] opt format=(hide-miscprops,hide-physprops,hide-columns) SELECT a + 1, min(b) FROM t WHERE k + a > b GROUP BY a ORDER BY a ---- -sort +project ├── stats: [rows=98.1771622] - ├── cost: 1101.88224 + ├── cost: 1103.84579 ├── key: (1) ├── fd: (1)-->(5,6) ├── prune: (1,5,6) - └── project - ├── stats: [rows=98.1771622] - ├── cost: 1086.91531 - ├── key: (1) - ├── fd: (1)-->(5,6) - ├── prune: (1,5,6) - ├── group-by - │ ├── stats: [rows=98.1771622, distinct(1)=98.1771622, null(1)=1] - │ ├── cost: 1084.94177 - │ ├── key: (1) - │ ├── fd: (1)-->(5) - │ ├── prune: (5) - │ ├── select - │ │ ├── stats: [rows=330, distinct(1)=98.1771622, null(1)=3.3, distinct(2)=100, null(2)=0] - │ │ ├── cost: 1074.04 - │ │ ├── key: (3) - │ │ ├── fd: (3)-->(1,2) - │ │ ├── interesting orderings: (+3) - │ │ ├── scan t.public.t - │ │ │ ├── stats: [rows=1000, distinct(1)=100, null(1)=10, distinct(2)=100, null(2)=10] - │ │ │ ├── cost: 1064.02 - │ │ │ ├── key: (3) - │ │ │ ├── fd: (3)-->(1,2) - │ │ │ ├── prune: (1-3) - │ │ │ └── interesting orderings: (+3) - │ │ └── filters - │ │ └── lt [type=bool, constraints=(/2: (/NULL - ])] - │ │ ├── variable: t.public.t.b [type=int] - │ │ └── plus [type=int] - │ │ ├── variable: t.public.t.k [type=int] - │ │ └── variable: t.public.t.a [type=int] - │ └── aggregations - │ └── min [type=int] - │ └── variable: t.public.t.b [type=int] - └── projections - └── plus [type=int] - ├── variable: t.public.t.a [type=int] - └── const: 1 [type=int] + ├── sort + │ ├── stats: [rows=98.1771622, distinct(1)=98.1771622, null(1)=1] + │ ├── cost: 1101.87224 + │ ├── key: (1) + │ ├── fd: (1)-->(5) + │ ├── prune: (5) + │ └── group-by + │ ├── stats: [rows=98.1771622, distinct(1)=98.1771622, null(1)=1] + │ ├── cost: 1084.94177 + │ ├── key: (1) + │ ├── fd: (1)-->(5) + │ ├── prune: (5) + │ ├── select + │ │ ├── stats: [rows=330, distinct(1)=98.1771622, null(1)=3.3, distinct(2)=100, null(2)=0] + │ │ ├── cost: 1074.04 + │ │ ├── key: (3) + │ │ ├── fd: (3)-->(1,2) + │ │ ├── interesting orderings: (+3) + │ │ ├── scan t.public.t + │ │ │ ├── stats: [rows=1000, distinct(1)=100, null(1)=10, distinct(2)=100, null(2)=10] + │ │ │ ├── cost: 1064.02 + │ │ │ ├── key: (3) + │ │ │ ├── fd: (3)-->(1,2) + │ │ │ ├── prune: (1-3) + │ │ │ └── interesting orderings: (+3) + │ │ └── filters + │ │ └── lt [type=bool, constraints=(/2: (/NULL - ])] + │ │ ├── variable: t.public.t.b [type=int] + │ │ └── plus [type=int] + │ │ ├── variable: t.public.t.k [type=int] + │ │ └── variable: t.public.t.a [type=int] + │ └── aggregations + │ └── min [type=int] + │ └── variable: t.public.t.b [type=int] + └── projections + └── plus [type=int] + ├── variable: t.public.t.a [type=int] + └── const: 1 [type=int] opt format=hide-all SELECT a + 1, min(b) FROM t WHERE k + a > b GROUP BY a ORDER BY a ---- -sort - └── project - ├── group-by - │ ├── select - │ │ ├── scan t - │ │ └── filters - │ │ └── b < (k + a) - │ └── aggregations - │ └── min - │ └── b - └── projections - └── a + 1 +project + ├── sort + │ └── group-by + │ ├── select + │ │ ├── scan t + │ │ └── filters + │ │ └── b < (k + a) + │ └── aggregations + │ └── min + │ └── b + └── projections + └── a + 1 diff --git a/pkg/sql/opt/memo/testdata/memo b/pkg/sql/opt/memo/testdata/memo index f5c895c0409f..75c2923bd289 100644 --- a/pkg/sql/opt/memo/testdata/memo +++ b/pkg/sql/opt/memo/testdata/memo @@ -132,22 +132,22 @@ memo (optimized, ~21KB, required=[presentation: y:2,x:4,c:8] [ordering: +2]) ├── G1: (project G2 G3 y x) │ ├── [presentation: y:2,x:4,c:8] [ordering: +2] │ │ ├── best: (project G2="[ordering: +2]" G3 y x) - │ │ └── cost: 1727.60 + │ │ └── cost: 1734.26 │ └── [] │ ├── best: (project G2 G3 y x) - │ └── cost: 1727.60 + │ └── cost: 1734.26 ├── G2: (limit G4 G5 ordering=+2) │ ├── [ordering: +2] │ │ ├── best: (limit G4="[ordering: +2] [limit hint: 10.00]" G5 ordering=+2) - │ │ └── cost: 1727.39 + │ │ └── cost: 1734.05 │ └── [] │ ├── best: (limit G4="[ordering: +2] [limit hint: 10.00]" G5 ordering=+2) - │ └── cost: 1727.39 + │ └── cost: 1734.05 ├── G3: (projections G6) ├── G4: (inner-join G7 G8 G9) (inner-join G7 G8 G9) (inner-join G8 G7 G9) (lookup-join G7 G10 b,keyCols=[7],outCols=(2,4,7)) (lookup-join G7 G10 b,keyCols=[7],outCols=(2,4,7)) (merge-join G8 G7 G10 inner-join,+4,+7) │ ├── [ordering: +2] [limit hint: 10.00] │ │ ├── best: (lookup-join G7="[ordering: +2] [limit hint: 100.00]" G10 b,keyCols=[7],outCols=(2,4,7)) - │ │ └── cost: 1727.28 + │ │ └── cost: 1733.94 │ └── [] │ ├── best: (inner-join G8 G7 G9) │ └── cost: 2116.42 @@ -156,10 +156,10 @@ memo (optimized, ~21KB, required=[presentation: y:2,x:4,c:8] [ordering: +2]) ├── G7: (project G13 G14 y) │ ├── [ordering: +2] [limit hint: 100.00] │ │ ├── best: (sort G7) - │ │ └── cost: 1123.27 + │ │ └── cost: 1129.93 │ ├── [ordering: +7] │ │ ├── best: (sort G7) - │ │ └── cost: 1123.27 + │ │ └── cost: 1129.93 │ └── [] │ ├── best: (project G13 G14 y) │ └── cost: 1060.72 @@ -177,7 +177,7 @@ memo (optimized, ~21KB, required=[presentation: y:2,x:4,c:8] [ordering: +2]) ├── G13: (select G16 G17) │ ├── [ordering: +2] [limit hint: 100.00] │ │ ├── best: (sort G13) - │ │ └── cost: 1116.59 + │ │ └── cost: 1123.26 │ └── [] │ ├── best: (select G16 G17) │ └── cost: 1054.04 @@ -186,7 +186,7 @@ memo (optimized, ~21KB, required=[presentation: y:2,x:4,c:8] [ordering: +2]) ├── G16: (scan a,cols=(1,2)) │ ├── [ordering: +2] [limit hint: 300.00] │ │ ├── best: (sort G16) - │ │ └── cost: 1263.35 + │ │ └── cost: 1283.35 │ └── [] │ ├── best: (scan a,cols=(1,2)) │ └── cost: 1044.02 @@ -336,11 +336,11 @@ memo (optimized, ~3KB, required=[presentation: array_agg:4]) ├── G1: (scalar-group-by G2 G3 cols=(),ordering=+2) │ └── [presentation: array_agg:4] │ ├── best: (scalar-group-by G2="[ordering: +2]" G3 cols=(),ordering=+2) - │ └── cost: 1273.38 + │ └── cost: 1293.38 ├── G2: (scan a,cols=(1,2)) │ ├── [ordering: +2] │ │ ├── best: (sort G2) - │ │ └── cost: 1263.35 + │ │ └── cost: 1283.35 │ └── [] │ ├── best: (scan a,cols=(1,2)) │ └── cost: 1044.02 diff --git a/pkg/sql/opt/memo/testdata/stats/inverted-geo b/pkg/sql/opt/memo/testdata/stats/inverted-geo index 5e7406760266..d75d6a70794b 100644 --- a/pkg/sql/opt/memo/testdata/stats/inverted-geo +++ b/pkg/sql/opt/memo/testdata/stats/inverted-geo @@ -94,16 +94,16 @@ memo (optimized, ~11KB, required=[presentation: i:1]) ├── G1: (project G2 G3 i) │ └── [presentation: i:1] │ ├── best: (project G2 G3 i) - │ └── cost: 4163.18 + │ └── cost: 4167.63 ├── G2: (limit G4 G5 ordering=+1) │ └── [] │ ├── best: (limit G4="[ordering: +1] [limit hint: 1.00]" G5 ordering=+1) - │ └── cost: 4163.16 + │ └── cost: 4167.61 ├── G3: (projections) ├── G4: (select G6 G7) (select G8 G7) │ ├── [ordering: +1] [limit hint: 1.00] │ │ ├── best: (sort G4) - │ │ └── cost: 4163.14 + │ │ └── cost: 4167.59 │ └── [] │ ├── best: (select G6 G7) │ └── cost: 4124.04 @@ -111,7 +111,7 @@ memo (optimized, ~11KB, required=[presentation: i:1]) ├── G6: (scan t,cols=(1,2)) │ ├── [ordering: +1] [limit hint: 9.00] │ │ ├── best: (sort G6) - │ │ └── cost: 2582.66 + │ │ └── cost: 2622.66 │ └── [] │ ├── best: (scan t,cols=(1,2)) │ └── cost: 2104.02 @@ -119,7 +119,7 @@ memo (optimized, ~11KB, required=[presentation: i:1]) ├── G8: (index-join G10 t,cols=(1,2)) │ ├── [ordering: +1] [limit hint: 13.50] │ │ ├── best: (sort G8) - │ │ └── cost: 22095.08 + │ │ └── cost: 22155.08 │ └── [] │ ├── best: (index-join G10 t,cols=(1,2)) │ └── cost: 21342.03 @@ -215,7 +215,7 @@ memo (optimized, ~11KB, required=[presentation: i:1]) ├── G6: (scan t,cols=(1,2)) │ ├── [ordering: +1] [limit hint: 9.00] │ │ ├── best: (sort G6) - │ │ └── cost: 2582.66 + │ │ └── cost: 2622.66 │ └── [] │ ├── best: (scan t,cols=(1,2)) │ └── cost: 2104.02 diff --git a/pkg/sql/opt/norm/testdata/rules/ordering b/pkg/sql/opt/norm/testdata/rules/ordering index 78751ddc449f..2f2756f94453 100644 --- a/pkg/sql/opt/norm/testdata/rules/ordering +++ b/pkg/sql/opt/norm/testdata/rules/ordering @@ -210,22 +210,21 @@ EXPLAIN SELECT b, b+1 AS plus, c FROM abcde ORDER BY b, plus, c explain ├── columns: info:8 ├── immutable - └── sort + └── project ├── columns: b:2 plus:7 c:3 ├── immutable ├── lax-key: (2,3) ├── fd: (2)-->(7) ├── ordering: +2,+3 - └── project - ├── columns: plus:7 b:2 c:3 - ├── immutable - ├── lax-key: (2,3) - ├── fd: (2)-->(7) - ├── scan abcde - │ ├── columns: b:2 c:3 - │ └── lax-key: (2,3) - └── projections - └── b:2 + 1 [as=plus:7, outer=(2), immutable] + ├── sort + │ ├── columns: b:2 c:3 + │ ├── lax-key: (2,3) + │ ├── ordering: +2,+3 + │ └── scan abcde + │ ├── columns: b:2 c:3 + │ └── lax-key: (2,3) + └── projections + └── b:2 + 1 [as=plus:7, outer=(2), immutable] # Regression: Explain a statement having constant column, but with no ordering. norm diff --git a/pkg/sql/opt/optbuilder/testdata/limit b/pkg/sql/opt/optbuilder/testdata/limit index 28536177bfcb..160ab6f45e03 100644 --- a/pkg/sql/opt/optbuilder/testdata/limit +++ b/pkg/sql/opt/optbuilder/testdata/limit @@ -136,25 +136,22 @@ limit ├── columns: sum:5 [hidden: v:2] ├── internal-ordering: -2 ├── ordering: -2 - ├── project + ├── sort │ ├── columns: v:2 sum:5 │ ├── ordering: -2 │ ├── limit hint: 10.00 - │ └── group-by - │ ├── columns: k:1!null v:2 sum:5 - │ ├── grouping columns: k:1!null v:2 - │ ├── ordering: -2 - │ ├── limit hint: 10.00 - │ ├── sort - │ │ ├── columns: k:1!null v:2 w:3 - │ │ ├── ordering: -2 - │ │ └── project - │ │ ├── columns: k:1!null v:2 w:3 - │ │ └── scan t - │ │ └── columns: k:1!null v:2 w:3 crdb_internal_mvcc_timestamp:4 - │ └── aggregations - │ └── sum [as=sum:5] - │ └── w:3 + │ └── project + │ ├── columns: v:2 sum:5 + │ └── group-by + │ ├── columns: k:1!null v:2 sum:5 + │ ├── grouping columns: k:1!null v:2 + │ ├── project + │ │ ├── columns: k:1!null v:2 w:3 + │ │ └── scan t + │ │ └── columns: k:1!null v:2 w:3 crdb_internal_mvcc_timestamp:4 + │ └── aggregations + │ └── sum [as=sum:5] + │ └── w:3 └── 10 build diff --git a/pkg/sql/opt/optbuilder/testdata/orderby b/pkg/sql/opt/optbuilder/testdata/orderby index 7d9813549022..69bb7454ef53 100644 --- a/pkg/sql/opt/optbuilder/testdata/orderby +++ b/pkg/sql/opt/optbuilder/testdata/orderby @@ -217,48 +217,44 @@ sort build SELECT * FROM t ORDER BY (b, t.*) ---- -project +sort ├── columns: a:1!null b:2 c:3 ├── ordering: +2,+1,+2,+3 - └── sort - ├── columns: a:1!null b:2 c:3 crdb_internal_mvcc_timestamp:4 - ├── ordering: +2,+1 + └── project + ├── columns: a:1!null b:2 c:3 └── scan t └── columns: a:1!null b:2 c:3 crdb_internal_mvcc_timestamp:4 build SELECT * FROM t ORDER BY (b, a), c ---- -project +sort ├── columns: a:1!null b:2 c:3 ├── ordering: +2,+1,+3 - └── sort - ├── columns: a:1!null b:2 c:3 crdb_internal_mvcc_timestamp:4 - ├── ordering: +2,+1 + └── project + ├── columns: a:1!null b:2 c:3 └── scan t └── columns: a:1!null b:2 c:3 crdb_internal_mvcc_timestamp:4 build SELECT * FROM t ORDER BY b, (a, c) ---- -project +sort ├── columns: a:1!null b:2 c:3 ├── ordering: +2,+1,+3 - └── sort - ├── columns: a:1!null b:2 c:3 crdb_internal_mvcc_timestamp:4 - ├── ordering: +2,+1 + └── project + ├── columns: a:1!null b:2 c:3 └── scan t └── columns: a:1!null b:2 c:3 crdb_internal_mvcc_timestamp:4 build SELECT * FROM t ORDER BY (b, (a, c)) ---- -project +sort ├── columns: a:1!null b:2 c:3 ├── ordering: +2,+1,+3 - └── sort - ├── columns: a:1!null b:2 c:3 crdb_internal_mvcc_timestamp:4 - ├── ordering: +2,+1 + └── project + ├── columns: a:1!null b:2 c:3 └── scan t └── columns: a:1!null b:2 c:3 crdb_internal_mvcc_timestamp:4 @@ -473,36 +469,38 @@ sort build SELECT generate_series, ARRAY[generate_series] FROM generate_series(1, 1) ORDER BY 1 ---- -sort +project ├── columns: generate_series:1 array:2 ├── ordering: +1 - └── project - ├── columns: array:2 generate_series:1 - ├── project-set - │ ├── columns: generate_series:1 - │ ├── values - │ │ └── () - │ └── zip - │ └── generate_series(1, 1) - └── projections - └── ARRAY[generate_series:1] [as=array:2] + ├── sort + │ ├── columns: generate_series:1 + │ ├── ordering: +1 + │ └── project-set + │ ├── columns: generate_series:1 + │ ├── values + │ │ └── () + │ └── zip + │ └── generate_series(1, 1) + └── projections + └── ARRAY[generate_series:1] [as=array:2] build SELECT generate_series, ARRAY[generate_series] FROM generate_series(1, 1) ORDER BY generate_series ---- -sort +project ├── columns: generate_series:1 array:2 ├── ordering: +1 - └── project - ├── columns: array:2 generate_series:1 - ├── project-set - │ ├── columns: generate_series:1 - │ ├── values - │ │ └── () - │ └── zip - │ └── generate_series(1, 1) - └── projections - └── ARRAY[generate_series:1] [as=array:2] + ├── sort + │ ├── columns: generate_series:1 + │ ├── ordering: +1 + │ └── project-set + │ ├── columns: generate_series:1 + │ ├── values + │ │ └── () + │ └── zip + │ └── generate_series(1, 1) + └── projections + └── ARRAY[generate_series:1] [as=array:2] build SELECT generate_series, ARRAY[generate_series] FROM generate_series(1, 1) ORDER BY -generate_series @@ -689,12 +687,11 @@ sort build SELECT a, b FROM abc ORDER BY b, c, a DESC ---- -project +sort ├── columns: a:1!null b:2!null [hidden: c:3!null] ├── ordering: +2,+3,-1 - └── sort - ├── columns: a:1!null b:2!null c:3!null d:4 crdb_internal_mvcc_timestamp:5 - ├── ordering: +2,+3 + └── project + ├── columns: a:1!null b:2!null c:3!null └── scan abc └── columns: a:1!null b:2!null c:3!null d:4 crdb_internal_mvcc_timestamp:5 diff --git a/pkg/sql/opt/optgen/exprgen/testdata/explain b/pkg/sql/opt/optgen/exprgen/testdata/explain index 0f658307276c..43813578dede 100644 --- a/pkg/sql/opt/optgen/exprgen/testdata/explain +++ b/pkg/sql/opt/optgen/exprgen/testdata/explain @@ -81,11 +81,11 @@ expr explain ├── mode: opt ├── stats: [rows=10] - ├── cost: 1283.35569 + ├── cost: 1303.35569 └── sort ├── columns: a:1(int) [hidden: t.public.abc.b:2(int)] ├── stats: [rows=1000] - ├── cost: 1283.34569 + ├── cost: 1303.34569 ├── ordering: +2 ├── interesting orderings: (+1,+2) └── scan t.public.abc diff --git a/pkg/sql/opt/optgen/exprgen/testdata/join b/pkg/sql/opt/optgen/exprgen/testdata/join index 023d02594311..89c93bf23474 100644 --- a/pkg/sql/opt/optgen/exprgen/testdata/join +++ b/pkg/sql/opt/optgen/exprgen/testdata/join @@ -80,12 +80,12 @@ inner-join (merge) ├── left ordering: +1 ├── right ordering: +6 ├── stats: [rows=9801, distinct(1)=99, null(1)=0, distinct(6)=99, null(6)=0] - ├── cost: 2704.71137 + ├── cost: 2764.71137 ├── fd: (1)==(6), (6)==(1) ├── sort │ ├── columns: t.public.abc.a:1(int) t.public.abc.b:2(int) t.public.abc.c:3(int) │ ├── stats: [rows=1000, distinct(1)=100, null(1)=10] - │ ├── cost: 1293.34569 + │ ├── cost: 1323.34569 │ ├── ordering: +1 │ ├── prune: (1-3) │ ├── interesting orderings: (+1,+2) @@ -98,7 +98,7 @@ inner-join (merge) ├── sort │ ├── columns: t.public.def.d:6(int) t.public.def.e:7(int) t.public.def.f:8(int) │ ├── stats: [rows=1000, distinct(6)=100, null(6)=10] - │ ├── cost: 1293.34569 + │ ├── cost: 1323.34569 │ ├── ordering: +6 │ ├── prune: (6-8) │ └── scan t.public.def @@ -123,13 +123,13 @@ inner-join-apply ├── columns: t.public.abc.a:1(int) t.public.abc.b:2(int) t.public.abc.c:3(int) t.public.def.d:6(int) t.public.def.e:7(int) t.public.def.f:8(int) ├── immutable ├── stats: [rows=333333.333] - ├── cost: 5619.40451 + ├── cost: 5649.40451 ├── prune: (8) ├── interesting orderings: (+1,+2) ├── sort │ ├── columns: t.public.abc.a:1(int) t.public.abc.b:2(int) t.public.abc.c:3(int) │ ├── stats: [rows=1000] - │ ├── cost: 1183.68784 + │ ├── cost: 1213.68784 │ ├── interesting orderings: (+1,+2) │ └── scan t.public.abc │ ├── columns: t.public.abc.a:1(int) t.public.abc.b:2(int) t.public.abc.c:3(int) diff --git a/pkg/sql/opt/optgen/exprgen/testdata/limit b/pkg/sql/opt/optgen/exprgen/testdata/limit index b76f3e7bada7..8d7017b9840c 100644 --- a/pkg/sql/opt/optgen/exprgen/testdata/limit +++ b/pkg/sql/opt/optgen/exprgen/testdata/limit @@ -39,12 +39,12 @@ limit ├── internal-ordering: +1 ├── cardinality: [0 - 10] ├── stats: [rows=10] - ├── cost: 1283.45569 + ├── cost: 1303.45569 ├── interesting orderings: (+1,+2) ├── sort │ ├── columns: t.public.abc.a:1(int) t.public.abc.b:2(int) │ ├── stats: [rows=1000] - │ ├── cost: 1283.34569 + │ ├── cost: 1303.34569 │ ├── ordering: +1 │ ├── limit hint: 10.00 │ ├── interesting orderings: (+1,+2) diff --git a/pkg/sql/opt/xform/coster.go b/pkg/sql/opt/xform/coster.go index 13c83483de49..c85c605b1aca 100644 --- a/pkg/sql/opt/xform/coster.go +++ b/pkg/sql/opt/xform/coster.go @@ -540,9 +540,14 @@ func (c *coster) computeSortCost(sort *memo.SortExpr, required *physical.Require numKeyCols := len(required.Ordering.Columns) numPreorderedCols := len(sort.InputOrdering.Columns) - stats := sort.Relational().Stats + rel := sort.Relational() + stats := rel.Stats numSegments := c.countSegments(sort) - cost := memo.Cost(0) + + // Start with a cost of storing each row; this takes the total number of + // columns into account so that a sort on fewer columns is preferred (e.g. + // sort before projecting a new column). + cost := memo.Cost(cpuCostFactor * float64(rel.OutputCols.Len()) * stats.RowCount) if !sort.InputOrdering.Any() { // Add the cost for finding the segments: each row is compared to the diff --git a/pkg/sql/opt/xform/testdata/coster/join b/pkg/sql/opt/xform/testdata/coster/join index 8ff13dacd2f1..4e38c34934bf 100644 --- a/pkg/sql/opt/xform/testdata/coster/join +++ b/pkg/sql/opt/xform/testdata/coster/join @@ -58,7 +58,7 @@ inner-join (merge) ├── left ordering: +1 ├── right ordering: +6 ├── stats: [rows=990, distinct(1)=99, null(1)=0, distinct(6)=99, null(6)=0] - ├── cost: 2347.27569 + ├── cost: 2357.27569 ├── fd: (1)==(6), (6)==(1) ├── scan a │ ├── columns: k:1!null @@ -69,7 +69,7 @@ inner-join (merge) ├── sort │ ├── columns: x:6 │ ├── stats: [rows=1000, distinct(6)=100, null(6)=10] - │ ├── cost: 1263.34569 + │ ├── cost: 1273.34569 │ ├── ordering: +6 │ └── scan b │ ├── columns: x:6 @@ -922,13 +922,13 @@ WHERE project ├── columns: attname:3!null atttypid:4!null typbasetype:50 typtype:32 ├── stats: [rows=198] - ├── cost: 2844.37877 + ├── cost: 2844.77877 └── inner-join (merge) ├── columns: attname:3!null atttypid:4!null oid:26!null typtype:32 typbasetype:50 ├── left ordering: +26 ├── right ordering: +4 ├── stats: [rows=198, distinct(4)=17.2927193, null(4)=0, distinct(26)=17.2927193, null(26)=0] - ├── cost: 2842.38877 + ├── cost: 2842.78877 ├── fd: (4)==(26), (26)==(4) ├── scan pg_type@secondary [as=t] │ ├── columns: oid:26!null typtype:32 typbasetype:50 @@ -938,7 +938,7 @@ project ├── sort │ ├── columns: attname:3!null atttypid:4 │ ├── stats: [rows=20, distinct(3)=2, null(3)=0, distinct(4)=18.2927193, null(4)=0.2] - │ ├── cost: 1376.17877 + │ ├── cost: 1376.57877 │ ├── ordering: +4 │ └── select │ ├── columns: attname:3!null atttypid:4 diff --git a/pkg/sql/opt/xform/testdata/coster/perturb-cost b/pkg/sql/opt/xform/testdata/coster/perturb-cost index 98164d9c8ce0..db6976343b69 100644 --- a/pkg/sql/opt/xform/testdata/coster/perturb-cost +++ b/pkg/sql/opt/xform/testdata/coster/perturb-cost @@ -22,7 +22,7 @@ SELECT * FROM a JOIN b ON a.x=b.x ORDER BY a.y sort ├── columns: x:1!null y:2 x:4!null ├── stats: [rows=1000, distinct(1)=1000, null(1)=0, distinct(4)=1000, null(4)=0] - ├── cost: 2327.38569 + ├── cost: 2357.38569 ├── key: (4) ├── fd: (1)-->(2), (1)==(4), (4)==(1) ├── ordering: +2 diff --git a/pkg/sql/opt/xform/testdata/coster/sort b/pkg/sql/opt/xform/testdata/coster/sort index e1801cd835a9..026ba8451983 100644 --- a/pkg/sql/opt/xform/testdata/coster/sort +++ b/pkg/sql/opt/xform/testdata/coster/sort @@ -15,7 +15,7 @@ SELECT f FROM a ORDER BY f DESC sort ├── columns: f:2!null ├── stats: [rows=1000] - ├── cost: 1273.34569 + ├── cost: 1283.34569 ├── ordering: -2 └── scan a ├── columns: f:2!null @@ -53,7 +53,7 @@ SELECT * FROM abc ORDER BY b, c, a sort ├── columns: a:1 b:2 c:3 ├── stats: [rows=1000] - ├── cost: 1305.40805 + ├── cost: 1335.40805 ├── ordering: +2,+3,+1 └── scan abc ├── columns: a:1 b:2 c:3 @@ -67,7 +67,7 @@ SELECT * FROM abc ORDER BY a, b, c sort (segmented) ├── columns: a:1 b:2 c:3 ├── stats: [rows=1000, distinct(1,2)=1000, null(1,2)=0.1] - ├── cost: 1114.03 + ├── cost: 1144.03 ├── ordering: +1,+2,+3 └── scan abc@ab ├── columns: a:1 b:2 c:3 @@ -82,7 +82,7 @@ SELECT * FROM abc ORDER BY c, b, a sort (segmented) ├── columns: a:1 b:2 c:3 ├── stats: [rows=1000, distinct(2,3)=1000, null(2,3)=0.1] - ├── cost: 1114.03 + ├── cost: 1144.03 ├── ordering: +3,+2,+1 └── scan abc@cb ├── columns: a:1 b:2 c:3 @@ -97,7 +97,7 @@ SELECT * FROM abc ORDER BY c, a, b sort (segmented) ├── columns: a:1 b:2 c:3 ├── stats: [rows=1000, distinct(3)=100, null(3)=10] - ├── cost: 1174.79049 + ├── cost: 1204.79049 ├── ordering: +3,+1,+2 └── scan abc@cb ├── columns: a:1 b:2 c:3 @@ -130,7 +130,7 @@ SELECT * FROM abc ORDER BY a, b, c sort (segmented) ├── columns: a:1 b:2 c:3 ├── stats: [rows=10000, distinct(1,2)=10, null(1,2)=0] - ├── cost: 13097.1869 + ├── cost: 13397.1869 ├── ordering: +1,+2,+3 └── scan abc@ab ├── columns: a:1 b:2 c:3 @@ -145,7 +145,7 @@ SELECT * FROM abc WHERE a = b ORDER BY b, a, c sort (segmented) ├── columns: a:1!null b:2!null c:3 ├── stats: [rows=2000, distinct(1)=2, null(1)=0, distinct(2)=2, null(2)=0] - ├── cost: 11262.6714 + ├── cost: 11322.6714 ├── fd: (1)==(2), (2)==(1) ├── ordering: +(1|2),+3 [actual: +1,+3] └── select diff --git a/pkg/sql/opt/xform/testdata/external/pgjdbc b/pkg/sql/opt/xform/testdata/external/pgjdbc index 2272f5089f2b..2e16976a8ed1 100644 --- a/pkg/sql/opt/xform/testdata/external/pgjdbc +++ b/pkg/sql/opt/xform/testdata/external/pgjdbc @@ -171,104 +171,98 @@ sort │ ├── window partition=(36) ordering=+41 opt(3,7,36,52) │ │ ├── columns: n.oid:2!null n.nspname:3!null c.oid:7!null c.relname:8!null c.relnamespace:9!null c.relkind:24!null attrelid:36!null attname:37 atttypid:38!null attlen:40 attnum:41!null atttypmod:44 a.attnotnull:48 attisdropped:52!null t.oid:60!null typtype:66 typnotnull:83 typbasetype:84 typtypmod:85 adrelid:93 adnum:94 adbin:95 objoid:98 classoid:99 objsubid:100 description:101 dc.oid:103 dc.relname:104 dc.relnamespace:105 dn.oid:132 dn.nspname:133 row_number:136 │ │ ├── fd: ()-->(3,52), (2)==(9), (9)==(2), (7)==(36), (36)==(7), (38)==(60), (60)==(38) - │ │ ├── inner-join (merge) + │ │ ├── inner-join (hash) │ │ │ ├── columns: n.oid:2!null n.nspname:3!null c.oid:7!null c.relname:8!null c.relnamespace:9!null c.relkind:24!null attrelid:36!null attname:37 atttypid:38!null attlen:40 attnum:41!null atttypmod:44 a.attnotnull:48 attisdropped:52!null t.oid:60!null typtype:66 typnotnull:83 typbasetype:84 typtypmod:85 adrelid:93 adnum:94 adbin:95 objoid:98 classoid:99 objsubid:100 description:101 dc.oid:103 dc.relname:104 dc.relnamespace:105 dn.oid:132 dn.nspname:133 - │ │ │ ├── left ordering: +60 - │ │ │ ├── right ordering: +38 │ │ │ ├── fd: ()-->(3,52), (2)==(9), (9)==(2), (7)==(36), (36)==(7), (38)==(60), (60)==(38) - │ │ │ ├── scan pg_type@secondary [as=t] - │ │ │ │ ├── columns: t.oid:60!null typtype:66 typnotnull:83 typbasetype:84 typtypmod:85 - │ │ │ │ └── ordering: +60 - │ │ │ ├── sort + │ │ │ ├── scan pg_type [as=t] + │ │ │ │ └── columns: t.oid:60!null typtype:66 typnotnull:83 typbasetype:84 typtypmod:85 + │ │ │ ├── left-join (hash) │ │ │ │ ├── columns: n.oid:2!null n.nspname:3!null c.oid:7!null c.relname:8!null c.relnamespace:9!null c.relkind:24!null attrelid:36!null attname:37 atttypid:38 attlen:40 attnum:41!null atttypmod:44 a.attnotnull:48 attisdropped:52!null adrelid:93 adnum:94 adbin:95 objoid:98 classoid:99 objsubid:100 description:101 dc.oid:103 dc.relname:104 dc.relnamespace:105 dn.oid:132 dn.nspname:133 │ │ │ │ ├── fd: ()-->(3,52), (7)==(36), (36)==(7), (2)==(9), (9)==(2) - │ │ │ │ ├── ordering: +38 opt(3,52) [actual: +38] - │ │ │ │ └── left-join (hash) - │ │ │ │ ├── columns: n.oid:2!null n.nspname:3!null c.oid:7!null c.relname:8!null c.relnamespace:9!null c.relkind:24!null attrelid:36!null attname:37 atttypid:38 attlen:40 attnum:41!null atttypmod:44 a.attnotnull:48 attisdropped:52!null adrelid:93 adnum:94 adbin:95 objoid:98 classoid:99 objsubid:100 description:101 dc.oid:103 dc.relname:104 dc.relnamespace:105 dn.oid:132 dn.nspname:133 - │ │ │ │ ├── fd: ()-->(3,52), (7)==(36), (36)==(7), (2)==(9), (9)==(2) - │ │ │ │ ├── right-join (hash) - │ │ │ │ │ ├── columns: n.oid:2!null n.nspname:3!null c.oid:7!null c.relname:8!null c.relnamespace:9!null c.relkind:24!null attrelid:36!null attname:37 atttypid:38 attlen:40 attnum:41!null atttypmod:44 a.attnotnull:48 attisdropped:52!null adrelid:93 adnum:94 adbin:95 objoid:98 classoid:99 objsubid:100 description:101 - │ │ │ │ │ ├── fd: ()-->(3,52), (7)==(36), (36)==(7), (2)==(9), (9)==(2) - │ │ │ │ │ ├── select - │ │ │ │ │ │ ├── columns: adrelid:93!null adnum:94!null adbin:95 - │ │ │ │ │ │ ├── scan pg_attrdef [as=def] - │ │ │ │ │ │ │ └── columns: adrelid:93!null adnum:94 adbin:95 - │ │ │ │ │ │ └── filters - │ │ │ │ │ │ └── adnum:94 > 0 [outer=(94), constraints=(/94: [/1 - ]; tight)] - │ │ │ │ │ ├── right-join (hash) - │ │ │ │ │ │ ├── columns: n.oid:2!null n.nspname:3!null c.oid:7!null c.relname:8!null c.relnamespace:9!null c.relkind:24!null attrelid:36!null attname:37 atttypid:38 attlen:40 attnum:41!null atttypmod:44 a.attnotnull:48 attisdropped:52!null objoid:98 classoid:99 objsubid:100 description:101 - │ │ │ │ │ │ ├── fd: ()-->(3,52), (7)==(36), (36)==(7), (2)==(9), (9)==(2) - │ │ │ │ │ │ ├── select - │ │ │ │ │ │ │ ├── columns: objoid:98 classoid:99 objsubid:100!null description:101 - │ │ │ │ │ │ │ ├── scan pg_description [as=dsc] - │ │ │ │ │ │ │ │ └── columns: objoid:98 classoid:99 objsubid:100 description:101 - │ │ │ │ │ │ │ └── filters - │ │ │ │ │ │ │ └── objsubid:100 > 0 [outer=(100), constraints=(/100: [/1 - ]; tight)] - │ │ │ │ │ │ ├── inner-join (hash) - │ │ │ │ │ │ │ ├── columns: n.oid:2!null n.nspname:3!null c.oid:7!null c.relname:8!null c.relnamespace:9!null c.relkind:24!null attrelid:36!null attname:37 atttypid:38 attlen:40 attnum:41!null atttypmod:44 a.attnotnull:48 attisdropped:52!null - │ │ │ │ │ │ │ ├── fd: ()-->(3,52), (2)==(9), (9)==(2), (7)==(36), (36)==(7) - │ │ │ │ │ │ │ ├── inner-join (merge) - │ │ │ │ │ │ │ │ ├── columns: c.oid:7!null c.relname:8!null c.relnamespace:9 c.relkind:24!null attrelid:36!null attname:37 atttypid:38 attlen:40 attnum:41!null atttypmod:44 a.attnotnull:48 attisdropped:52!null - │ │ │ │ │ │ │ │ ├── left ordering: +7 - │ │ │ │ │ │ │ │ ├── right ordering: +36 - │ │ │ │ │ │ │ │ ├── fd: ()-->(52), (7)==(36), (36)==(7) - │ │ │ │ │ │ │ │ ├── select - │ │ │ │ │ │ │ │ │ ├── columns: c.oid:7!null c.relname:8!null c.relnamespace:9 c.relkind:24!null - │ │ │ │ │ │ │ │ │ ├── ordering: +7 - │ │ │ │ │ │ │ │ │ ├── scan pg_class@secondary [as=c] - │ │ │ │ │ │ │ │ │ │ ├── columns: c.oid:7!null c.relname:8!null c.relnamespace:9 c.relkind:24 - │ │ │ │ │ │ │ │ │ │ └── ordering: +7 - │ │ │ │ │ │ │ │ │ └── filters - │ │ │ │ │ │ │ │ │ ├── c.relkind:24 IN ('f', 'm', 'p', 'r', 'v') [outer=(24), constraints=(/24: [/'f' - /'f'] [/'m' - /'m'] [/'p' - /'p'] [/'r' - /'r'] [/'v' - /'v']; tight)] - │ │ │ │ │ │ │ │ │ └── c.relname:8 LIKE '%' [outer=(8), constraints=(/8: (/NULL - ])] - │ │ │ │ │ │ │ │ ├── select - │ │ │ │ │ │ │ │ │ ├── columns: attrelid:36!null attname:37 atttypid:38 attlen:40 attnum:41!null atttypmod:44 a.attnotnull:48 attisdropped:52!null - │ │ │ │ │ │ │ │ │ ├── fd: ()-->(52) - │ │ │ │ │ │ │ │ │ ├── ordering: +36 opt(52) [actual: +36] - │ │ │ │ │ │ │ │ │ ├── scan pg_attribute@secondary [as=a] - │ │ │ │ │ │ │ │ │ │ ├── columns: attrelid:36!null attname:37 atttypid:38 attlen:40 attnum:41 atttypmod:44 a.attnotnull:48 attisdropped:52 - │ │ │ │ │ │ │ │ │ │ └── ordering: +36 opt(52) [actual: +36] - │ │ │ │ │ │ │ │ │ └── filters - │ │ │ │ │ │ │ │ │ ├── attnum:41 > 0 [outer=(41), constraints=(/41: [/1 - ]; tight)] - │ │ │ │ │ │ │ │ │ └── NOT attisdropped:52 [outer=(52), constraints=(/52: [/false - /false]; tight), fd=()-->(52)] - │ │ │ │ │ │ │ │ └── filters (true) - │ │ │ │ │ │ │ ├── select - │ │ │ │ │ │ │ │ ├── columns: n.oid:2 n.nspname:3!null - │ │ │ │ │ │ │ │ ├── fd: ()-->(3) - │ │ │ │ │ │ │ │ ├── scan pg_namespace [as=n] - │ │ │ │ │ │ │ │ │ └── columns: n.oid:2 n.nspname:3!null - │ │ │ │ │ │ │ │ └── filters - │ │ │ │ │ │ │ │ └── n.nspname:3 LIKE 'public' [outer=(3), constraints=(/3: [/'public' - /'public']; tight), fd=()-->(3)] - │ │ │ │ │ │ │ └── filters - │ │ │ │ │ │ │ └── c.relnamespace:9 = n.oid:2 [outer=(2,9), constraints=(/2: (/NULL - ]; /9: (/NULL - ]), fd=(2)==(9), (9)==(2)] - │ │ │ │ │ │ └── filters - │ │ │ │ │ │ ├── c.oid:7 = objoid:98 [outer=(7,98), constraints=(/7: (/NULL - ]; /98: (/NULL - ]), fd=(7)==(98), (98)==(7)] - │ │ │ │ │ │ └── attnum:41 = objsubid:100 [outer=(41,100), constraints=(/41: (/NULL - ]; /100: (/NULL - ]), fd=(41)==(100), (100)==(41)] - │ │ │ │ │ └── filters - │ │ │ │ │ ├── attrelid:36 = adrelid:93 [outer=(36,93), constraints=(/36: (/NULL - ]; /93: (/NULL - ]), fd=(36)==(93), (93)==(36)] - │ │ │ │ │ └── attnum:41 = adnum:94 [outer=(41,94), constraints=(/41: (/NULL - ]; /94: (/NULL - ]), fd=(41)==(94), (94)==(41)] - │ │ │ │ ├── left-join (hash) - │ │ │ │ │ ├── columns: dc.oid:103!null dc.relname:104!null dc.relnamespace:105 dn.oid:132 dn.nspname:133 - │ │ │ │ │ ├── fd: ()-->(104) - │ │ │ │ │ ├── select - │ │ │ │ │ │ ├── columns: dc.oid:103!null dc.relname:104!null dc.relnamespace:105 - │ │ │ │ │ │ ├── fd: ()-->(104) - │ │ │ │ │ │ ├── scan pg_class [as=dc] - │ │ │ │ │ │ │ └── columns: dc.oid:103!null dc.relname:104!null dc.relnamespace:105 - │ │ │ │ │ │ └── filters - │ │ │ │ │ │ └── dc.relname:104 = 'pg_class' [outer=(104), constraints=(/104: [/'pg_class' - /'pg_class']; tight), fd=()-->(104)] - │ │ │ │ │ ├── select - │ │ │ │ │ │ ├── columns: dn.oid:132 dn.nspname:133!null - │ │ │ │ │ │ ├── fd: ()-->(133) - │ │ │ │ │ │ ├── scan pg_namespace [as=dn] - │ │ │ │ │ │ │ └── columns: dn.oid:132 dn.nspname:133!null - │ │ │ │ │ │ └── filters - │ │ │ │ │ │ └── dn.nspname:133 = 'pg_catalog' [outer=(133), constraints=(/133: [/'pg_catalog' - /'pg_catalog']; tight), fd=()-->(133)] - │ │ │ │ │ └── filters - │ │ │ │ │ └── dc.relnamespace:105 = dn.oid:132 [outer=(105,132), constraints=(/105: (/NULL - ]; /132: (/NULL - ]), fd=(105)==(132), (132)==(105)] - │ │ │ │ └── filters - │ │ │ │ └── dc.oid:103 = classoid:99 [outer=(99,103), constraints=(/99: (/NULL - ]; /103: (/NULL - ]), fd=(99)==(103), (103)==(99)] - │ │ │ └── filters (true) + │ │ │ │ ├── right-join (hash) + │ │ │ │ │ ├── columns: n.oid:2!null n.nspname:3!null c.oid:7!null c.relname:8!null c.relnamespace:9!null c.relkind:24!null attrelid:36!null attname:37 atttypid:38 attlen:40 attnum:41!null atttypmod:44 a.attnotnull:48 attisdropped:52!null adrelid:93 adnum:94 adbin:95 objoid:98 classoid:99 objsubid:100 description:101 + │ │ │ │ │ ├── fd: ()-->(3,52), (7)==(36), (36)==(7), (2)==(9), (9)==(2) + │ │ │ │ │ ├── select + │ │ │ │ │ │ ├── columns: adrelid:93!null adnum:94!null adbin:95 + │ │ │ │ │ │ ├── scan pg_attrdef [as=def] + │ │ │ │ │ │ │ └── columns: adrelid:93!null adnum:94 adbin:95 + │ │ │ │ │ │ └── filters + │ │ │ │ │ │ └── adnum:94 > 0 [outer=(94), constraints=(/94: [/1 - ]; tight)] + │ │ │ │ │ ├── right-join (hash) + │ │ │ │ │ │ ├── columns: n.oid:2!null n.nspname:3!null c.oid:7!null c.relname:8!null c.relnamespace:9!null c.relkind:24!null attrelid:36!null attname:37 atttypid:38 attlen:40 attnum:41!null atttypmod:44 a.attnotnull:48 attisdropped:52!null objoid:98 classoid:99 objsubid:100 description:101 + │ │ │ │ │ │ ├── fd: ()-->(3,52), (7)==(36), (36)==(7), (2)==(9), (9)==(2) + │ │ │ │ │ │ ├── select + │ │ │ │ │ │ │ ├── columns: objoid:98 classoid:99 objsubid:100!null description:101 + │ │ │ │ │ │ │ ├── scan pg_description [as=dsc] + │ │ │ │ │ │ │ │ └── columns: objoid:98 classoid:99 objsubid:100 description:101 + │ │ │ │ │ │ │ └── filters + │ │ │ │ │ │ │ └── objsubid:100 > 0 [outer=(100), constraints=(/100: [/1 - ]; tight)] + │ │ │ │ │ │ ├── inner-join (hash) + │ │ │ │ │ │ │ ├── columns: n.oid:2!null n.nspname:3!null c.oid:7!null c.relname:8!null c.relnamespace:9!null c.relkind:24!null attrelid:36!null attname:37 atttypid:38 attlen:40 attnum:41!null atttypmod:44 a.attnotnull:48 attisdropped:52!null + │ │ │ │ │ │ │ ├── fd: ()-->(3,52), (2)==(9), (9)==(2), (7)==(36), (36)==(7) + │ │ │ │ │ │ │ ├── inner-join (merge) + │ │ │ │ │ │ │ │ ├── columns: c.oid:7!null c.relname:8!null c.relnamespace:9 c.relkind:24!null attrelid:36!null attname:37 atttypid:38 attlen:40 attnum:41!null atttypmod:44 a.attnotnull:48 attisdropped:52!null + │ │ │ │ │ │ │ │ ├── left ordering: +7 + │ │ │ │ │ │ │ │ ├── right ordering: +36 + │ │ │ │ │ │ │ │ ├── fd: ()-->(52), (7)==(36), (36)==(7) + │ │ │ │ │ │ │ │ ├── select + │ │ │ │ │ │ │ │ │ ├── columns: c.oid:7!null c.relname:8!null c.relnamespace:9 c.relkind:24!null + │ │ │ │ │ │ │ │ │ ├── ordering: +7 + │ │ │ │ │ │ │ │ │ ├── scan pg_class@secondary [as=c] + │ │ │ │ │ │ │ │ │ │ ├── columns: c.oid:7!null c.relname:8!null c.relnamespace:9 c.relkind:24 + │ │ │ │ │ │ │ │ │ │ └── ordering: +7 + │ │ │ │ │ │ │ │ │ └── filters + │ │ │ │ │ │ │ │ │ ├── c.relkind:24 IN ('f', 'm', 'p', 'r', 'v') [outer=(24), constraints=(/24: [/'f' - /'f'] [/'m' - /'m'] [/'p' - /'p'] [/'r' - /'r'] [/'v' - /'v']; tight)] + │ │ │ │ │ │ │ │ │ └── c.relname:8 LIKE '%' [outer=(8), constraints=(/8: (/NULL - ])] + │ │ │ │ │ │ │ │ ├── select + │ │ │ │ │ │ │ │ │ ├── columns: attrelid:36!null attname:37 atttypid:38 attlen:40 attnum:41!null atttypmod:44 a.attnotnull:48 attisdropped:52!null + │ │ │ │ │ │ │ │ │ ├── fd: ()-->(52) + │ │ │ │ │ │ │ │ │ ├── ordering: +36 opt(52) [actual: +36] + │ │ │ │ │ │ │ │ │ ├── scan pg_attribute@secondary [as=a] + │ │ │ │ │ │ │ │ │ │ ├── columns: attrelid:36!null attname:37 atttypid:38 attlen:40 attnum:41 atttypmod:44 a.attnotnull:48 attisdropped:52 + │ │ │ │ │ │ │ │ │ │ └── ordering: +36 opt(52) [actual: +36] + │ │ │ │ │ │ │ │ │ └── filters + │ │ │ │ │ │ │ │ │ ├── attnum:41 > 0 [outer=(41), constraints=(/41: [/1 - ]; tight)] + │ │ │ │ │ │ │ │ │ └── NOT attisdropped:52 [outer=(52), constraints=(/52: [/false - /false]; tight), fd=()-->(52)] + │ │ │ │ │ │ │ │ └── filters (true) + │ │ │ │ │ │ │ ├── select + │ │ │ │ │ │ │ │ ├── columns: n.oid:2 n.nspname:3!null + │ │ │ │ │ │ │ │ ├── fd: ()-->(3) + │ │ │ │ │ │ │ │ ├── scan pg_namespace [as=n] + │ │ │ │ │ │ │ │ │ └── columns: n.oid:2 n.nspname:3!null + │ │ │ │ │ │ │ │ └── filters + │ │ │ │ │ │ │ │ └── n.nspname:3 LIKE 'public' [outer=(3), constraints=(/3: [/'public' - /'public']; tight), fd=()-->(3)] + │ │ │ │ │ │ │ └── filters + │ │ │ │ │ │ │ └── c.relnamespace:9 = n.oid:2 [outer=(2,9), constraints=(/2: (/NULL - ]; /9: (/NULL - ]), fd=(2)==(9), (9)==(2)] + │ │ │ │ │ │ └── filters + │ │ │ │ │ │ ├── c.oid:7 = objoid:98 [outer=(7,98), constraints=(/7: (/NULL - ]; /98: (/NULL - ]), fd=(7)==(98), (98)==(7)] + │ │ │ │ │ │ └── attnum:41 = objsubid:100 [outer=(41,100), constraints=(/41: (/NULL - ]; /100: (/NULL - ]), fd=(41)==(100), (100)==(41)] + │ │ │ │ │ └── filters + │ │ │ │ │ ├── attrelid:36 = adrelid:93 [outer=(36,93), constraints=(/36: (/NULL - ]; /93: (/NULL - ]), fd=(36)==(93), (93)==(36)] + │ │ │ │ │ └── attnum:41 = adnum:94 [outer=(41,94), constraints=(/41: (/NULL - ]; /94: (/NULL - ]), fd=(41)==(94), (94)==(41)] + │ │ │ │ ├── left-join (hash) + │ │ │ │ │ ├── columns: dc.oid:103!null dc.relname:104!null dc.relnamespace:105 dn.oid:132 dn.nspname:133 + │ │ │ │ │ ├── fd: ()-->(104) + │ │ │ │ │ ├── select + │ │ │ │ │ │ ├── columns: dc.oid:103!null dc.relname:104!null dc.relnamespace:105 + │ │ │ │ │ │ ├── fd: ()-->(104) + │ │ │ │ │ │ ├── scan pg_class [as=dc] + │ │ │ │ │ │ │ └── columns: dc.oid:103!null dc.relname:104!null dc.relnamespace:105 + │ │ │ │ │ │ └── filters + │ │ │ │ │ │ └── dc.relname:104 = 'pg_class' [outer=(104), constraints=(/104: [/'pg_class' - /'pg_class']; tight), fd=()-->(104)] + │ │ │ │ │ ├── select + │ │ │ │ │ │ ├── columns: dn.oid:132 dn.nspname:133!null + │ │ │ │ │ │ ├── fd: ()-->(133) + │ │ │ │ │ │ ├── scan pg_namespace [as=dn] + │ │ │ │ │ │ │ └── columns: dn.oid:132 dn.nspname:133!null + │ │ │ │ │ │ └── filters + │ │ │ │ │ │ └── dn.nspname:133 = 'pg_catalog' [outer=(133), constraints=(/133: [/'pg_catalog' - /'pg_catalog']; tight), fd=()-->(133)] + │ │ │ │ │ └── filters + │ │ │ │ │ └── dc.relnamespace:105 = dn.oid:132 [outer=(105,132), constraints=(/105: (/NULL - ]; /132: (/NULL - ]), fd=(105)==(132), (132)==(105)] + │ │ │ │ └── filters + │ │ │ │ └── dc.oid:103 = classoid:99 [outer=(99,103), constraints=(/99: (/NULL - ]; /103: (/NULL - ]), fd=(99)==(103), (103)==(99)] + │ │ │ └── filters + │ │ │ └── atttypid:38 = t.oid:60 [outer=(38,60), constraints=(/38: (/NULL - ]; /60: (/NULL - ]), fd=(38)==(60), (60)==(38)] │ │ └── windows │ │ └── row-number [as=row_number:136] │ └── filters diff --git a/pkg/sql/opt/xform/testdata/external/tpce b/pkg/sql/opt/xform/testdata/external/tpce index 1c7254f4ab7f..aece6458f775 100644 --- a/pkg/sql/opt/xform/testdata/external/tpce +++ b/pkg/sql/opt/xform/testdata/external/tpce @@ -298,31 +298,32 @@ project ├── key: (17,21) ├── fd: ()-->(9), (1)-->(2,6,7), (17,19)-->(18), (21)-->(22), (19)==(21), (21)==(19), (1)==(17), (17)==(1) ├── ordering: -18 opt(9) [actual: -18] - ├── sort + ├── inner-join (lookup status_type) │ ├── columns: t_id:1!null t_dts:2!null t_s_symb:6!null t_qty:7!null t_ca_id:9!null th_t_id:17!null th_dts:18!null th_st_id:19!null st_id:21!null st_name:22!null + │ ├── key columns: [19] = [21] + │ ├── lookup columns are key │ ├── key: (17,21) │ ├── fd: ()-->(9), (1)-->(2,6,7), (17,19)-->(18), (21)-->(22), (19)==(21), (21)==(19), (1)==(17), (17)==(1) │ ├── ordering: -18 opt(9) [actual: -18] │ ├── limit hint: 30.00 - │ └── inner-join (lookup status_type) - │ ├── columns: t_id:1!null t_dts:2!null t_s_symb:6!null t_qty:7!null t_ca_id:9!null th_t_id:17!null th_dts:18!null th_st_id:19!null st_id:21!null st_name:22!null - │ ├── key columns: [19] = [21] - │ ├── lookup columns are key - │ ├── key: (17,21) - │ ├── fd: ()-->(9), (1)-->(2,6,7), (17,19)-->(18), (21)-->(22), (19)==(21), (21)==(19), (1)==(17), (17)==(1) - │ ├── inner-join (lookup trade_history) - │ │ ├── columns: t_id:1!null t_dts:2!null t_s_symb:6!null t_qty:7!null t_ca_id:9!null th_t_id:17!null th_dts:18!null th_st_id:19!null - │ │ ├── key columns: [1] = [17] - │ │ ├── key: (17,19) - │ │ ├── fd: ()-->(9), (1)-->(2,6,7), (17,19)-->(18), (1)==(17), (17)==(1) - │ │ ├── scan trade@secondary - │ │ │ ├── columns: t_id:1!null t_dts:2!null t_s_symb:6!null t_qty:7!null t_ca_id:9!null - │ │ │ ├── constraint: /9/-2/1: [/0 - /0] - │ │ │ ├── limit: 10 - │ │ │ ├── key: (1) - │ │ │ └── fd: ()-->(9), (1)-->(2,6,7) - │ │ └── filters (true) - │ └── filters (true) + │ ├── sort + │ │ ├── columns: t_id:1!null t_dts:2!null t_s_symb:6!null t_qty:7!null t_ca_id:9!null th_t_id:17!null th_dts:18!null th_st_id:19!null + │ │ ├── key: (17,19) + │ │ ├── fd: ()-->(9), (1)-->(2,6,7), (17,19)-->(18), (1)==(17), (17)==(1) + │ │ ├── ordering: -18 opt(9) [actual: -18] + │ │ └── inner-join (lookup trade_history) + │ │ ├── columns: t_id:1!null t_dts:2!null t_s_symb:6!null t_qty:7!null t_ca_id:9!null th_t_id:17!null th_dts:18!null th_st_id:19!null + │ │ ├── key columns: [1] = [17] + │ │ ├── key: (17,19) + │ │ ├── fd: ()-->(9), (1)-->(2,6,7), (17,19)-->(18), (1)==(17), (17)==(1) + │ │ ├── scan trade@secondary + │ │ │ ├── columns: t_id:1!null t_dts:2!null t_s_symb:6!null t_qty:7!null t_ca_id:9!null + │ │ │ ├── constraint: /9/-2/1: [/0 - /0] + │ │ │ ├── limit: 10 + │ │ │ ├── key: (1) + │ │ │ └── fd: ()-->(9), (1)-->(2,6,7) + │ │ └── filters (true) + │ └── filters (true) └── 30 # -------------------------------------------------- diff --git a/pkg/sql/opt/xform/testdata/external/tpch-no-stats b/pkg/sql/opt/xform/testdata/external/tpch-no-stats index 51053f693e95..ac5c4515eb5f 100644 --- a/pkg/sql/opt/xform/testdata/external/tpch-no-stats +++ b/pkg/sql/opt/xform/testdata/external/tpch-no-stats @@ -168,7 +168,6 @@ project │ ├── group-by │ │ ├── columns: p_partkey:1!null p_mfgr:3!null s_name:12!null s_address:13!null s_phone:15!null s_acctbal:16!null s_comment:17!null ps_partkey:19!null ps_suppkey:20!null ps_supplycost:22!null n_name:26!null min:57!null │ │ ├── grouping columns: ps_partkey:19!null ps_suppkey:20!null - │ │ ├── internal-ordering: +(1|19|34),+(11|20) opt(6,31,54) │ │ ├── key: (19,20) │ │ ├── fd: (1)-->(3), (19,20)-->(1,3,12,13,15-17,22,26,57), (1)==(19), (19)==(1), (20)-->(12,13,15-17,26) │ │ ├── inner-join (lookup region) @@ -177,70 +176,58 @@ project │ │ │ ├── lookup columns are key │ │ │ ├── key: (20,34,40) │ │ │ ├── fd: ()-->(6,31,54), (1)-->(3,5), (11)-->(12-17), (19,20)-->(22), (11)==(20), (20)==(11), (25)-->(26,27), (27)==(30), (30)==(27), (14)==(25), (25)==(14), (1)==(19,34), (19)==(1,34), (34,35)-->(37), (40)-->(43), (48)-->(50), (50)==(53), (53)==(50), (43)==(48), (48)==(43), (35)==(40), (40)==(35), (34)==(1,19) - │ │ │ ├── ordering: +(1|19|34),+(11|20) opt(6,31,54) [actual: +1,+20] │ │ │ ├── inner-join (lookup nation) │ │ │ │ ├── columns: p_partkey:1!null p_mfgr:3!null p_type:5!null p_size:6!null s_suppkey:11!null s_name:12!null s_address:13!null s_nationkey:14!null s_phone:15!null s_acctbal:16!null s_comment:17!null ps_partkey:19!null ps_suppkey:20!null ps_supplycost:22!null n_nationkey:25!null n_name:26!null n_regionkey:27!null r_regionkey:30!null r_name:31!null ps_partkey:34!null ps_suppkey:35!null ps_supplycost:37!null s_suppkey:40!null s_nationkey:43!null n_nationkey:48!null n_regionkey:50!null │ │ │ │ ├── key columns: [43] = [48] │ │ │ │ ├── lookup columns are key │ │ │ │ ├── key: (20,34,40) │ │ │ │ ├── fd: ()-->(6,31), (1)-->(3,5), (25)-->(26,27), (11)-->(12-17), (19,20)-->(22), (34,35)-->(37), (40)-->(43), (48)-->(50), (43)==(48), (48)==(43), (35)==(40), (40)==(35), (19)==(1,34), (34)==(1,19), (11)==(20), (20)==(11), (14)==(25), (25)==(14), (27)==(30), (30)==(27), (1)==(19,34) - │ │ │ │ ├── ordering: +(1|19|34),+(11|20) opt(6,31) [actual: +1,+20] │ │ │ │ ├── inner-join (lookup supplier) │ │ │ │ │ ├── columns: p_partkey:1!null p_mfgr:3!null p_type:5!null p_size:6!null s_suppkey:11!null s_name:12!null s_address:13!null s_nationkey:14!null s_phone:15!null s_acctbal:16!null s_comment:17!null ps_partkey:19!null ps_suppkey:20!null ps_supplycost:22!null n_nationkey:25!null n_name:26!null n_regionkey:27!null r_regionkey:30!null r_name:31!null ps_partkey:34!null ps_suppkey:35!null ps_supplycost:37!null s_suppkey:40!null s_nationkey:43!null │ │ │ │ │ ├── key columns: [35] = [40] │ │ │ │ │ ├── lookup columns are key │ │ │ │ │ ├── key: (20,34,40) │ │ │ │ │ ├── fd: ()-->(6,31), (1)-->(3,5), (25)-->(26,27), (11)-->(12-17), (19,20)-->(22), (34,35)-->(37), (40)-->(43), (35)==(40), (40)==(35), (19)==(1,34), (34)==(1,19), (11)==(20), (20)==(11), (14)==(25), (25)==(14), (27)==(30), (30)==(27), (1)==(19,34) - │ │ │ │ │ ├── ordering: +(1|19|34),+(11|20) opt(6,31) [actual: +1,+20] │ │ │ │ │ ├── inner-join (lookup partsupp) │ │ │ │ │ │ ├── columns: p_partkey:1!null p_mfgr:3!null p_type:5!null p_size:6!null s_suppkey:11!null s_name:12!null s_address:13!null s_nationkey:14!null s_phone:15!null s_acctbal:16!null s_comment:17!null ps_partkey:19!null ps_suppkey:20!null ps_supplycost:22!null n_nationkey:25!null n_name:26!null n_regionkey:27!null r_regionkey:30!null r_name:31!null ps_partkey:34!null ps_suppkey:35!null ps_supplycost:37!null │ │ │ │ │ │ ├── key columns: [1] = [34] │ │ │ │ │ │ ├── key: (20,34,35) │ │ │ │ │ │ ├── fd: ()-->(6,31), (1)-->(3,5), (25)-->(26,27), (11)-->(12-17), (19,20)-->(22), (34,35)-->(37), (19)==(1,34), (34)==(1,19), (11)==(20), (20)==(11), (14)==(25), (25)==(14), (27)==(30), (30)==(27), (1)==(19,34) - │ │ │ │ │ │ ├── ordering: +(1|19|34),+(11|20) opt(6,31) [actual: +1,+20] │ │ │ │ │ │ ├── inner-join (lookup region) │ │ │ │ │ │ │ ├── columns: p_partkey:1!null p_mfgr:3!null p_type:5!null p_size:6!null s_suppkey:11!null s_name:12!null s_address:13!null s_nationkey:14!null s_phone:15!null s_acctbal:16!null s_comment:17!null ps_partkey:19!null ps_suppkey:20!null ps_supplycost:22!null n_nationkey:25!null n_name:26!null n_regionkey:27!null r_regionkey:30!null r_name:31!null │ │ │ │ │ │ │ ├── key columns: [27] = [30] │ │ │ │ │ │ │ ├── lookup columns are key │ │ │ │ │ │ │ ├── key: (19,20) │ │ │ │ │ │ │ ├── fd: ()-->(6,31), (1)-->(3,5), (11)-->(12-17), (19,20)-->(22), (11)==(20), (20)==(11), (25)-->(26,27), (27)==(30), (30)==(27), (14)==(25), (25)==(14), (1)==(19), (19)==(1) - │ │ │ │ │ │ │ ├── ordering: +(1|19),+(11|20) opt(6,31) [actual: +1,+20] │ │ │ │ │ │ │ ├── inner-join (lookup nation) │ │ │ │ │ │ │ │ ├── columns: p_partkey:1!null p_mfgr:3!null p_type:5!null p_size:6!null s_suppkey:11!null s_name:12!null s_address:13!null s_nationkey:14!null s_phone:15!null s_acctbal:16!null s_comment:17!null ps_partkey:19!null ps_suppkey:20!null ps_supplycost:22!null n_nationkey:25!null n_name:26!null n_regionkey:27!null │ │ │ │ │ │ │ │ ├── key columns: [14] = [25] │ │ │ │ │ │ │ │ ├── lookup columns are key │ │ │ │ │ │ │ │ ├── key: (19,20) │ │ │ │ │ │ │ │ ├── fd: ()-->(6), (1)-->(3,5), (19,20)-->(22), (11)-->(12-17), (25)-->(26,27), (14)==(25), (25)==(14), (11)==(20), (20)==(11), (1)==(19), (19)==(1) - │ │ │ │ │ │ │ │ ├── ordering: +(1|19),+(11|20) opt(6) [actual: +1,+20] │ │ │ │ │ │ │ │ ├── inner-join (lookup supplier) │ │ │ │ │ │ │ │ │ ├── columns: p_partkey:1!null p_mfgr:3!null p_type:5!null p_size:6!null s_suppkey:11!null s_name:12!null s_address:13!null s_nationkey:14!null s_phone:15!null s_acctbal:16!null s_comment:17!null ps_partkey:19!null ps_suppkey:20!null ps_supplycost:22!null │ │ │ │ │ │ │ │ │ ├── key columns: [20] = [11] │ │ │ │ │ │ │ │ │ ├── lookup columns are key │ │ │ │ │ │ │ │ │ ├── key: (19,20) │ │ │ │ │ │ │ │ │ ├── fd: ()-->(6), (1)-->(3,5), (11)-->(12-17), (19,20)-->(22), (11)==(20), (20)==(11), (1)==(19), (19)==(1) - │ │ │ │ │ │ │ │ │ ├── ordering: +(1|19),+(11|20) opt(6) [actual: +1,+20] - │ │ │ │ │ │ │ │ │ ├── sort + │ │ │ │ │ │ │ │ │ ├── inner-join (lookup partsupp) │ │ │ │ │ │ │ │ │ │ ├── columns: p_partkey:1!null p_mfgr:3!null p_type:5!null p_size:6!null ps_partkey:19!null ps_suppkey:20!null ps_supplycost:22!null + │ │ │ │ │ │ │ │ │ │ ├── key columns: [1] = [19] │ │ │ │ │ │ │ │ │ │ ├── key: (19,20) │ │ │ │ │ │ │ │ │ │ ├── fd: ()-->(6), (1)-->(3,5), (19,20)-->(22), (1)==(19), (19)==(1) - │ │ │ │ │ │ │ │ │ │ ├── ordering: +(1|19),+20 opt(6) [actual: +1,+20] - │ │ │ │ │ │ │ │ │ │ └── inner-join (lookup partsupp) - │ │ │ │ │ │ │ │ │ │ ├── columns: p_partkey:1!null p_mfgr:3!null p_type:5!null p_size:6!null ps_partkey:19!null ps_suppkey:20!null ps_supplycost:22!null - │ │ │ │ │ │ │ │ │ │ ├── key columns: [1] = [19] - │ │ │ │ │ │ │ │ │ │ ├── key: (19,20) - │ │ │ │ │ │ │ │ │ │ ├── fd: ()-->(6), (1)-->(3,5), (19,20)-->(22), (1)==(19), (19)==(1) - │ │ │ │ │ │ │ │ │ │ ├── select - │ │ │ │ │ │ │ │ │ │ │ ├── columns: p_partkey:1!null p_mfgr:3!null p_type:5!null p_size:6!null - │ │ │ │ │ │ │ │ │ │ │ ├── key: (1) - │ │ │ │ │ │ │ │ │ │ │ ├── fd: ()-->(6), (1)-->(3,5) - │ │ │ │ │ │ │ │ │ │ │ ├── scan part - │ │ │ │ │ │ │ │ │ │ │ │ ├── columns: p_partkey:1!null p_mfgr:3!null p_type:5!null p_size:6!null - │ │ │ │ │ │ │ │ │ │ │ │ ├── key: (1) - │ │ │ │ │ │ │ │ │ │ │ │ └── fd: (1)-->(3,5,6) - │ │ │ │ │ │ │ │ │ │ │ └── filters - │ │ │ │ │ │ │ │ │ │ │ ├── p_size:6 = 15 [outer=(6), constraints=(/6: [/15 - /15]; tight), fd=()-->(6)] - │ │ │ │ │ │ │ │ │ │ │ └── p_type:5 LIKE '%BRASS' [outer=(5), constraints=(/5: (/NULL - ])] - │ │ │ │ │ │ │ │ │ │ └── filters (true) + │ │ │ │ │ │ │ │ │ │ ├── select + │ │ │ │ │ │ │ │ │ │ │ ├── columns: p_partkey:1!null p_mfgr:3!null p_type:5!null p_size:6!null + │ │ │ │ │ │ │ │ │ │ │ ├── key: (1) + │ │ │ │ │ │ │ │ │ │ │ ├── fd: ()-->(6), (1)-->(3,5) + │ │ │ │ │ │ │ │ │ │ │ ├── scan part + │ │ │ │ │ │ │ │ │ │ │ │ ├── columns: p_partkey:1!null p_mfgr:3!null p_type:5!null p_size:6!null + │ │ │ │ │ │ │ │ │ │ │ │ ├── key: (1) + │ │ │ │ │ │ │ │ │ │ │ │ └── fd: (1)-->(3,5,6) + │ │ │ │ │ │ │ │ │ │ │ └── filters + │ │ │ │ │ │ │ │ │ │ │ ├── p_size:6 = 15 [outer=(6), constraints=(/6: [/15 - /15]; tight), fd=()-->(6)] + │ │ │ │ │ │ │ │ │ │ │ └── p_type:5 LIKE '%BRASS' [outer=(5), constraints=(/5: (/NULL - ])] + │ │ │ │ │ │ │ │ │ │ └── filters (true) │ │ │ │ │ │ │ │ │ └── filters (true) │ │ │ │ │ │ │ │ └── filters (true) │ │ │ │ │ │ │ └── filters @@ -1554,83 +1541,85 @@ WHERE ORDER BY s_suppkey; ---- -sort +project ├── columns: s_suppkey:1!null s_name:2!null s_address:3!null s_phone:5!null total_revenue:27!null ├── immutable ├── key: (1) ├── fd: (1)-->(2,3,5,27) ├── ordering: +1 - └── project - ├── columns: s_suppkey:1!null s_name:2!null s_address:3!null s_phone:5!null sum:27!null + └── inner-join (lookup supplier) + ├── columns: s_suppkey:1!null s_name:2!null s_address:3!null s_phone:5!null l_suppkey:11!null sum:27!null + ├── key columns: [11] = [1] + ├── lookup columns are key ├── immutable - ├── key: (1) - ├── fd: (1)-->(2,3,5,27) - └── inner-join (lookup supplier) - ├── columns: s_suppkey:1!null s_name:2!null s_address:3!null s_phone:5!null l_suppkey:11!null sum:27!null - ├── key columns: [11] = [1] - ├── lookup columns are key - ├── immutable - ├── key: (11) - ├── fd: (1)-->(2,3,5), (11)-->(27), (1)==(11), (11)==(1) - ├── select - │ ├── columns: l_suppkey:11!null sum:27!null - │ ├── immutable - │ ├── key: (11) - │ ├── fd: (11)-->(27) - │ ├── group-by - │ │ ├── columns: l_suppkey:11!null sum:27!null - │ │ ├── grouping columns: l_suppkey:11!null - │ │ ├── immutable - │ │ ├── key: (11) - │ │ ├── fd: (11)-->(27) - │ │ ├── project - │ │ │ ├── columns: column26:26!null l_suppkey:11!null - │ │ │ ├── immutable - │ │ │ ├── select - │ │ │ │ ├── columns: l_suppkey:11!null l_extendedprice:14!null l_discount:15!null l_shipdate:19!null - │ │ │ │ ├── scan lineitem - │ │ │ │ │ └── columns: l_suppkey:11!null l_extendedprice:14!null l_discount:15!null l_shipdate:19!null - │ │ │ │ └── filters - │ │ │ │ └── (l_shipdate:19 >= '1996-01-01') AND (l_shipdate:19 < '1996-04-01') [outer=(19), constraints=(/19: [/'1996-01-01' - /'1996-03-31']; tight)] - │ │ │ └── projections - │ │ │ └── l_extendedprice:14 * (1.0 - l_discount:15) [as=column26:26, outer=(14,15), immutable] - │ │ └── aggregations - │ │ └── sum [as=sum:27, outer=(26)] - │ │ └── column26:26 - │ └── filters - │ └── eq [outer=(27), immutable, subquery, constraints=(/27: (/NULL - ])] - │ ├── sum:27 - │ └── subquery - │ └── scalar-group-by - │ ├── columns: max:47 - │ ├── cardinality: [1 - 1] - │ ├── immutable - │ ├── key: () - │ ├── fd: ()-->(47) - │ ├── group-by - │ │ ├── columns: l_suppkey:30!null sum:46!null - │ │ ├── grouping columns: l_suppkey:30!null - │ │ ├── immutable - │ │ ├── key: (30) - │ │ ├── fd: (30)-->(46) - │ │ ├── project - │ │ │ ├── columns: column45:45!null l_suppkey:30!null - │ │ │ ├── immutable - │ │ │ ├── select - │ │ │ │ ├── columns: l_suppkey:30!null l_extendedprice:33!null l_discount:34!null l_shipdate:38!null - │ │ │ │ ├── scan lineitem - │ │ │ │ │ └── columns: l_suppkey:30!null l_extendedprice:33!null l_discount:34!null l_shipdate:38!null - │ │ │ │ └── filters - │ │ │ │ └── (l_shipdate:38 >= '1996-01-01') AND (l_shipdate:38 < '1996-04-01') [outer=(38), constraints=(/38: [/'1996-01-01' - /'1996-03-31']; tight)] - │ │ │ └── projections - │ │ │ └── l_extendedprice:33 * (1.0 - l_discount:34) [as=column45:45, outer=(33,34), immutable] - │ │ └── aggregations - │ │ └── sum [as=sum:46, outer=(45)] - │ │ └── column45:45 - │ └── aggregations - │ └── max [as=max:47, outer=(46)] - │ └── sum:46 - └── filters (true) + ├── key: (11) + ├── fd: (1)-->(2,3,5), (11)-->(27), (1)==(11), (11)==(1) + ├── ordering: +(1|11) [actual: +11] + ├── sort + │ ├── columns: l_suppkey:11!null sum:27!null + │ ├── immutable + │ ├── key: (11) + │ ├── fd: (11)-->(27) + │ ├── ordering: +11 + │ └── select + │ ├── columns: l_suppkey:11!null sum:27!null + │ ├── immutable + │ ├── key: (11) + │ ├── fd: (11)-->(27) + │ ├── group-by + │ │ ├── columns: l_suppkey:11!null sum:27!null + │ │ ├── grouping columns: l_suppkey:11!null + │ │ ├── immutable + │ │ ├── key: (11) + │ │ ├── fd: (11)-->(27) + │ │ ├── project + │ │ │ ├── columns: column26:26!null l_suppkey:11!null + │ │ │ ├── immutable + │ │ │ ├── select + │ │ │ │ ├── columns: l_suppkey:11!null l_extendedprice:14!null l_discount:15!null l_shipdate:19!null + │ │ │ │ ├── scan lineitem + │ │ │ │ │ └── columns: l_suppkey:11!null l_extendedprice:14!null l_discount:15!null l_shipdate:19!null + │ │ │ │ └── filters + │ │ │ │ └── (l_shipdate:19 >= '1996-01-01') AND (l_shipdate:19 < '1996-04-01') [outer=(19), constraints=(/19: [/'1996-01-01' - /'1996-03-31']; tight)] + │ │ │ └── projections + │ │ │ └── l_extendedprice:14 * (1.0 - l_discount:15) [as=column26:26, outer=(14,15), immutable] + │ │ └── aggregations + │ │ └── sum [as=sum:27, outer=(26)] + │ │ └── column26:26 + │ └── filters + │ └── eq [outer=(27), immutable, subquery, constraints=(/27: (/NULL - ])] + │ ├── sum:27 + │ └── subquery + │ └── scalar-group-by + │ ├── columns: max:47 + │ ├── cardinality: [1 - 1] + │ ├── immutable + │ ├── key: () + │ ├── fd: ()-->(47) + │ ├── group-by + │ │ ├── columns: l_suppkey:30!null sum:46!null + │ │ ├── grouping columns: l_suppkey:30!null + │ │ ├── immutable + │ │ ├── key: (30) + │ │ ├── fd: (30)-->(46) + │ │ ├── project + │ │ │ ├── columns: column45:45!null l_suppkey:30!null + │ │ │ ├── immutable + │ │ │ ├── select + │ │ │ │ ├── columns: l_suppkey:30!null l_extendedprice:33!null l_discount:34!null l_shipdate:38!null + │ │ │ │ ├── scan lineitem + │ │ │ │ │ └── columns: l_suppkey:30!null l_extendedprice:33!null l_discount:34!null l_shipdate:38!null + │ │ │ │ └── filters + │ │ │ │ └── (l_shipdate:38 >= '1996-01-01') AND (l_shipdate:38 < '1996-04-01') [outer=(38), constraints=(/38: [/'1996-01-01' - /'1996-03-31']; tight)] + │ │ │ └── projections + │ │ │ └── l_extendedprice:33 * (1.0 - l_discount:34) [as=column45:45, outer=(33,34), immutable] + │ │ └── aggregations + │ │ └── sum [as=sum:46, outer=(45)] + │ │ └── column45:45 + │ └── aggregations + │ └── max [as=max:47, outer=(46)] + │ └── sum:46 + └── filters (true) # -------------------------------------------------- # Q16 diff --git a/pkg/sql/opt/xform/testdata/physprops/ordering b/pkg/sql/opt/xform/testdata/physprops/ordering index 2ee8d04d5346..645956dc8c51 100644 --- a/pkg/sql/opt/xform/testdata/physprops/ordering +++ b/pkg/sql/opt/xform/testdata/physprops/ordering @@ -325,14 +325,14 @@ memo (optimized, ~5KB, required=[presentation: y:2,z:3] [ordering: +2]) ├── G1: (project G2 G3 y z) │ ├── [presentation: y:2,z:3] [ordering: +2] │ │ ├── best: (sort G1) - │ │ └── cost: 1149.93 + │ │ └── cost: 1156.60 │ └── [] │ ├── best: (project G2 G3 y z) │ └── cost: 1087.38 ├── G2: (select G4 G5) │ ├── [ordering: +2] │ │ ├── best: (sort G2) - │ │ └── cost: 1146.59 + │ │ └── cost: 1156.59 │ └── [] │ ├── best: (select G4 G5) │ └── cost: 1084.04 @@ -340,7 +340,7 @@ memo (optimized, ~5KB, required=[presentation: y:2,z:3] [ordering: +2]) ├── G4: (scan a,cols=(1-3)) │ ├── [ordering: +2] │ │ ├── best: (sort G4) - │ │ └── cost: 1293.35 + │ │ └── cost: 1323.35 │ └── [] │ ├── best: (scan a,cols=(1-3)) │ └── cost: 1074.02 @@ -640,11 +640,11 @@ memo (optimized, ~3KB, required=[presentation: info:6]) ├── G1: (explain G2 [presentation: x:1,y:2,z:3,s:4] [ordering: +2]) │ └── [presentation: info:6] │ ├── best: (explain G2="[presentation: x:1,y:2,z:3,s:4] [ordering: +2]" [presentation: x:1,y:2,z:3,s:4] [ordering: +2]) - │ └── cost: 1303.36 + │ └── cost: 1343.36 └── G2: (scan a,cols=(1-4)) ├── [presentation: x:1,y:2,z:3,s:4] [ordering: +2] │ ├── best: (sort G2) - │ └── cost: 1303.35 + │ └── cost: 1343.35 └── [] ├── best: (scan a,cols=(1-4)) └── cost: 1084.02 @@ -676,7 +676,7 @@ memo (optimized, ~5KB, required=[presentation: y:2] [ordering: +7]) ├── G1: (project G2 G3 y) │ ├── [presentation: y:2] [ordering: +7] │ │ ├── best: (sort G1) - │ │ └── cost: 1303.37 + │ │ └── cost: 1323.37 │ └── [] │ ├── best: (project G2 G3 y) │ └── cost: 1084.04 @@ -715,14 +715,14 @@ memo (optimized, ~5KB, required=[presentation: y:2] [ordering: +2,+6]) ├── G1: (ordinality G2 ordering=+2) │ ├── [presentation: y:2] [ordering: +2,+6] │ │ ├── best: (ordinality G2="[ordering: +2]" ordering=+2) - │ │ └── cost: 1283.36 + │ │ └── cost: 1293.36 │ └── [] │ ├── best: (ordinality G2="[ordering: +2]" ordering=+2) - │ └── cost: 1283.36 + │ └── cost: 1293.36 └── G2: (scan a,cols=(2)) ├── [ordering: +2] │ ├── best: (sort G2) - │ └── cost: 1273.35 + │ └── cost: 1283.35 └── [] ├── best: (scan a,cols=(2)) └── cost: 1054.02 @@ -734,14 +734,14 @@ memo (optimized, ~5KB, required=[presentation: y:2] [ordering: +6]) ├── G1: (ordinality G2 ordering=+2) │ ├── [presentation: y:2] [ordering: +6] │ │ ├── best: (ordinality G2="[ordering: +2]" ordering=+2) - │ │ └── cost: 1283.36 + │ │ └── cost: 1293.36 │ └── [] │ ├── best: (ordinality G2="[ordering: +2]" ordering=+2) - │ └── cost: 1283.36 + │ └── cost: 1293.36 └── G2: (scan a,cols=(2)) ├── [ordering: +2] │ ├── best: (sort G2) - │ └── cost: 1273.35 + │ └── cost: 1283.35 └── [] ├── best: (scan a,cols=(2)) └── cost: 1054.02 @@ -753,7 +753,7 @@ memo (optimized, ~4KB, required=[presentation: y:2] [ordering: -6]) ├── G1: (ordinality G2) │ ├── [presentation: y:2] [ordering: -6] │ │ ├── best: (sort G1) - │ │ └── cost: 1283.36 + │ │ └── cost: 1303.36 │ └── [] │ ├── best: (ordinality G2) │ └── cost: 1064.03 diff --git a/pkg/sql/opt/xform/testdata/rules/groupby b/pkg/sql/opt/xform/testdata/rules/groupby index e542ebd5349b..36e3366f6e36 100644 --- a/pkg/sql/opt/xform/testdata/rules/groupby +++ b/pkg/sql/opt/xform/testdata/rules/groupby @@ -524,7 +524,7 @@ memo (optimized, ~6KB, required=[presentation: min:6]) ├── G2: (scan abc,cols=(2)) │ ├── [ordering: +2] [limit hint: 1.01] │ │ ├── best: (sort G2) - │ │ └── cost: 1273.35 + │ │ └── cost: 1283.35 │ └── [] │ ├── best: (scan abc,cols=(2)) │ └── cost: 1054.02 @@ -532,13 +532,13 @@ memo (optimized, ~6KB, required=[presentation: min:6]) ├── G4: (limit G7 G8 ordering=+2) │ └── [] │ ├── best: (limit G7="[ordering: +2] [limit hint: 1.00]" G8 ordering=+2) - │ └── cost: 1280.91 + │ └── cost: 1290.81 ├── G5: (aggregations G9) ├── G6: (min G10) ├── G7: (select G2 G11) │ ├── [ordering: +2] [limit hint: 1.00] │ │ ├── best: (sort G7) - │ │ └── cost: 1280.89 + │ │ └── cost: 1290.79 │ └── [] │ ├── best: (select G2 G11) │ └── cost: 1064.04 @@ -586,7 +586,7 @@ memo (optimized, ~6KB, required=[presentation: max:6]) ├── G2: (scan abc,cols=(2)) │ ├── [ordering: -2] [limit hint: 1.01] │ │ ├── best: (sort G2) - │ │ └── cost: 1273.35 + │ │ └── cost: 1283.35 │ └── [] │ ├── best: (scan abc,cols=(2)) │ └── cost: 1054.02 @@ -594,13 +594,13 @@ memo (optimized, ~6KB, required=[presentation: max:6]) ├── G4: (limit G7 G8 ordering=-2) │ └── [] │ ├── best: (limit G7="[ordering: -2] [limit hint: 1.00]" G8 ordering=-2) - │ └── cost: 1280.91 + │ └── cost: 1290.81 ├── G5: (aggregations G9) ├── G6: (max G10) ├── G7: (select G2 G11) │ ├── [ordering: -2] [limit hint: 1.00] │ │ ├── best: (sort G7) - │ │ └── cost: 1280.89 + │ │ └── cost: 1290.79 │ └── [] │ ├── best: (select G2 G11) │ └── cost: 1064.04 @@ -694,7 +694,7 @@ memo (optimized, ~6KB, required=[presentation: max:6]) ├── G2: (scan abc,cols=(2)) │ ├── [ordering: -2] [limit hint: 1.01] │ │ ├── best: (sort G2) - │ │ └── cost: 1273.35 + │ │ └── cost: 1283.35 │ └── [] │ ├── best: (scan abc,cols=(2)) │ └── cost: 1054.02 @@ -702,13 +702,13 @@ memo (optimized, ~6KB, required=[presentation: max:6]) ├── G4: (limit G7 G8 ordering=-2) │ └── [] │ ├── best: (limit G7="[ordering: -2] [limit hint: 1.00]" G8 ordering=-2) - │ └── cost: 1280.91 + │ └── cost: 1290.81 ├── G5: (aggregations G9) ├── G6: (max G10) ├── G7: (select G2 G11) │ ├── [ordering: -2] [limit hint: 1.00] │ │ ├── best: (sort G7) - │ │ └── cost: 1280.89 + │ │ └── cost: 1290.79 │ └── [] │ ├── best: (select G2 G11) │ └── cost: 1064.04 @@ -1257,13 +1257,13 @@ memo (optimized, ~12KB, required=[presentation: array_agg:6]) │ │ └── cost: 1083.13 │ ├── [ordering: +(2|3),+4] │ │ ├── best: (sort G4) - │ │ └── cost: 1084.02 + │ │ └── cost: 1084.42 │ ├── [ordering: +(2|3)] │ │ ├── best: (select G8="[ordering: +2]" G7) │ │ └── cost: 1083.13 │ ├── [ordering: +4,+(2|3)] │ │ ├── best: (sort G4) - │ │ └── cost: 1084.02 + │ │ └── cost: 1084.42 │ └── [] │ ├── best: (select G8 G7) │ └── cost: 1083.13 @@ -1274,13 +1274,13 @@ memo (optimized, ~12KB, required=[presentation: array_agg:6]) │ │ └── cost: 1084.02 │ ├── [ordering: +2,+4] │ │ ├── best: (sort G6="[ordering: +2]") - │ │ └── cost: 1180.47 + │ │ └── cost: 1220.47 │ ├── [ordering: +2] │ │ ├── best: (scan kuvw@uvw,cols=(1-4)) │ │ └── cost: 1084.02 │ ├── [ordering: +4,+2] │ │ ├── best: (sort G6="[ordering: +4]") - │ │ └── cost: 1180.47 + │ │ └── cost: 1220.47 │ ├── [ordering: +4] │ │ ├── best: (scan kuvw@wvu,cols=(1-4)) │ │ └── cost: 1084.02 @@ -1294,35 +1294,35 @@ memo (optimized, ~12KB, required=[presentation: array_agg:6]) │ │ └── cost: 1073.21 │ ├── [ordering: +2,+4] │ │ ├── best: (sort G8="[ordering: +2]") - │ │ └── cost: 1168.41 + │ │ └── cost: 1208.01 │ ├── [ordering: +2] │ │ ├── best: (scan kuvw@uvw,cols=(1-4),constrained) │ │ └── cost: 1073.21 │ ├── [ordering: +4,+2] │ │ ├── best: (sort G8) - │ │ └── cost: 1300.90 + │ │ └── cost: 1340.50 │ ├── [ordering: +4] │ │ ├── best: (sort G8) - │ │ └── cost: 1290.06 + │ │ └── cost: 1329.66 │ └── [] │ ├── best: (scan kuvw@uvw,cols=(1-4),constrained) │ └── cost: 1073.21 ├── G9: (scan kuvw@vw,cols=(1-4),constrained) │ ├── [ordering: +2 opt(4)] │ │ ├── best: (sort G9) - │ │ └── cost: 1290.06 + │ │ └── cost: 1329.66 │ ├── [ordering: +2,+4] │ │ ├── best: (sort G9) - │ │ └── cost: 1300.90 + │ │ └── cost: 1340.50 │ ├── [ordering: +2] │ │ ├── best: (sort G9) - │ │ └── cost: 1290.06 + │ │ └── cost: 1329.66 │ ├── [ordering: +4,+2] │ │ ├── best: (sort G9) - │ │ └── cost: 1300.90 + │ │ └── cost: 1340.50 │ ├── [ordering: +4] │ │ ├── best: (sort G9) - │ │ └── cost: 1290.06 + │ │ └── cost: 1329.66 │ └── [] │ ├── best: (scan kuvw@vw,cols=(1-4),constrained) │ └── cost: 1073.21 @@ -1351,7 +1351,7 @@ memo (optimized, ~12KB, required=[presentation: sum:6]) │ │ └── cost: 1083.13 │ ├── [ordering: +4] │ │ ├── best: (sort G4) - │ │ └── cost: 1083.98 + │ │ └── cost: 1084.37 │ └── [] │ ├── best: (select G8 G7) │ └── cost: 1083.13 @@ -1373,17 +1373,17 @@ memo (optimized, ~12KB, required=[presentation: sum:6]) │ │ └── cost: 1073.21 │ ├── [ordering: +4] │ │ ├── best: (sort G8) - │ │ └── cost: 1290.06 + │ │ └── cost: 1329.66 │ └── [] │ ├── best: (scan kuvw@uvw,cols=(1-4),constrained) │ └── cost: 1073.21 ├── G9: (scan kuvw@vw,cols=(1-4),constrained) │ ├── [ordering: +2] │ │ ├── best: (sort G9) - │ │ └── cost: 1290.06 + │ │ └── cost: 1329.66 │ ├── [ordering: +4] │ │ ├── best: (sort G9) - │ │ └── cost: 1290.06 + │ │ └── cost: 1329.66 │ └── [] │ ├── best: (scan kuvw@vw,cols=(1-4),constrained) │ └── cost: 1073.21 @@ -1540,14 +1540,14 @@ memo (optimized, ~4KB, required=[presentation: u:2,v:3,w:4] [ordering: +2]) ├── G1: (distinct-on G2 G3 cols=(2),ordering=+4 opt(2)) (distinct-on G2 G3 cols=(2),ordering=+4) │ ├── [presentation: u:2,v:3,w:4] [ordering: +2] │ │ ├── best: (sort G1) - │ │ └── cost: 1130.34 + │ │ └── cost: 1133.34 │ └── [] │ ├── best: (distinct-on G2="[ordering: +4 opt(2)]" G3 cols=(2),ordering=+4 opt(2)) │ └── cost: 1115.04 ├── G2: (scan kuvw,cols=(2-4)) (scan kuvw@uvw,cols=(2-4)) (scan kuvw@wvu,cols=(2-4)) (scan kuvw@vw,cols=(2-4)) (scan kuvw@w,cols=(2-4)) │ ├── [ordering: +2,+4] │ │ ├── best: (sort G2="[ordering: +2]") - │ │ └── cost: 1170.47 + │ │ └── cost: 1200.47 │ ├── [ordering: +2] │ │ ├── best: (scan kuvw@uvw,cols=(2-4)) │ │ └── cost: 1074.02 @@ -1605,14 +1605,14 @@ memo (optimized, ~4KB, required=[presentation: u:2,v:3,w:4] [ordering: +4,+2]) ├── G1: (distinct-on G2 G3 cols=(2,4),ordering=-3 opt(2,4)) │ ├── [presentation: u:2,v:3,w:4] [ordering: +4,+2] │ │ ├── best: (distinct-on G2="[ordering: +4,+2,-3]" G3 cols=(2,4),ordering=-3 opt(2,4)) - │ │ └── cost: 1214.81 + │ │ └── cost: 1244.81 │ └── [] │ ├── best: (distinct-on G2="[ordering: -3 opt(2,4)]" G3 cols=(2,4),ordering=-3 opt(2,4)) │ └── cost: 1223.70 ├── G2: (scan kuvw,cols=(2-4)) (scan kuvw@uvw,cols=(2-4)) (scan kuvw@wvu,cols=(2-4)) (scan kuvw@vw,cols=(2-4)) (scan kuvw@w,cols=(2-4)) │ ├── [ordering: +4,+2,-3] │ │ ├── best: (sort G2="[ordering: +4]") - │ │ └── cost: 1174.79 + │ │ └── cost: 1204.79 │ ├── [ordering: +4] │ │ ├── best: (scan kuvw@wvu,cols=(2-4)) │ │ └── cost: 1074.02 @@ -1633,20 +1633,20 @@ memo (optimized, ~4KB, required=[presentation: u:2,v:3,w:4] [ordering: +4]) ├── G1: (distinct-on G2 G3 cols=(4),ordering=-2,+3 opt(4)) │ ├── [presentation: u:2,v:3,w:4] [ordering: +4] │ │ ├── best: (distinct-on G2="[ordering: +4,-2,+3]" G3 cols=(4),ordering=-2,+3 opt(4)) - │ │ └── cost: 1205.81 + │ │ └── cost: 1235.81 │ └── [] │ ├── best: (distinct-on G2="[ordering: -2,+3 opt(4)]" G3 cols=(4),ordering=-2,+3 opt(4)) - │ └── cost: 1345.33 + │ └── cost: 1375.33 ├── G2: (scan kuvw,cols=(2-4)) (scan kuvw@uvw,cols=(2-4)) (scan kuvw@wvu,cols=(2-4)) (scan kuvw@vw,cols=(2-4)) (scan kuvw@w,cols=(2-4)) │ ├── [ordering: +4,-2,+3] │ │ ├── best: (sort G2="[ordering: +4]") - │ │ └── cost: 1174.79 + │ │ └── cost: 1204.79 │ ├── [ordering: +4] │ │ ├── best: (scan kuvw@wvu,cols=(2-4)) │ │ └── cost: 1074.02 │ ├── [ordering: -2,+3 opt(4)] │ │ ├── best: (sort G2) - │ │ └── cost: 1304.31 + │ │ └── cost: 1334.31 │ └── [] │ ├── best: (scan kuvw,cols=(2-4)) │ └── cost: 1074.02 @@ -1663,17 +1663,17 @@ memo (optimized, ~4KB, required=[presentation: u:2,v:3,w:4] [ordering: -4]) ├── G1: (distinct-on G2 G3 cols=(4),ordering=-2,+3 opt(4)) │ ├── [presentation: u:2,v:3,w:4] [ordering: -4] │ │ ├── best: (distinct-on G2="[ordering: -4,-2,+3]" G3 cols=(4),ordering=-2,+3 opt(4)) - │ │ └── cost: 1336.43 + │ │ └── cost: 1366.43 │ └── [] │ ├── best: (distinct-on G2="[ordering: -2,+3 opt(4)]" G3 cols=(4),ordering=-2,+3 opt(4)) - │ └── cost: 1345.33 + │ └── cost: 1375.33 ├── G2: (scan kuvw,cols=(2-4)) (scan kuvw@uvw,cols=(2-4)) (scan kuvw@wvu,cols=(2-4)) (scan kuvw@vw,cols=(2-4)) (scan kuvw@w,cols=(2-4)) │ ├── [ordering: -2,+3 opt(4)] │ │ ├── best: (sort G2) - │ │ └── cost: 1304.31 + │ │ └── cost: 1334.31 │ ├── [ordering: -4,-2,+3] │ │ ├── best: (sort G2) - │ │ └── cost: 1305.41 + │ │ └── cost: 1335.41 │ └── [] │ ├── best: (scan kuvw,cols=(2-4)) │ └── cost: 1074.02 @@ -1690,20 +1690,20 @@ memo (optimized, ~4KB, required=[presentation: u:2,v:3,w:4] [ordering: +4]) ├── G1: (distinct-on G2 G3 cols=(4),ordering=+2,-3 opt(4)) │ ├── [presentation: u:2,v:3,w:4] [ordering: +4] │ │ ├── best: (distinct-on G2="[ordering: +4,+2,-3]" G3 cols=(4),ordering=+2,-3 opt(4)) - │ │ └── cost: 1205.81 + │ │ └── cost: 1235.81 │ └── [] │ ├── best: (distinct-on G2="[ordering: +2,-3 opt(4)]" G3 cols=(4),ordering=+2,-3 opt(4)) - │ └── cost: 1211.49 + │ └── cost: 1241.49 ├── G2: (scan kuvw,cols=(2-4)) (scan kuvw@uvw,cols=(2-4)) (scan kuvw@wvu,cols=(2-4)) (scan kuvw@vw,cols=(2-4)) (scan kuvw@w,cols=(2-4)) │ ├── [ordering: +2,-3 opt(4)] │ │ ├── best: (sort G2="[ordering: +2]") - │ │ └── cost: 1170.47 + │ │ └── cost: 1200.47 │ ├── [ordering: +2] │ │ ├── best: (scan kuvw@uvw,cols=(2-4)) │ │ └── cost: 1074.02 │ ├── [ordering: +4,+2,-3] │ │ ├── best: (sort G2="[ordering: +4]") - │ │ └── cost: 1174.79 + │ │ └── cost: 1204.79 │ ├── [ordering: +4] │ │ ├── best: (scan kuvw@wvu,cols=(2-4)) │ │ └── cost: 1074.02 @@ -1724,22 +1724,22 @@ memo (optimized, ~36KB, required=[presentation: w:10] [ordering: +11,+1]) ├── G1: (project G2 G3 x) │ ├── [presentation: w:10] [ordering: +11,+1] │ │ ├── best: (sort G1) - │ │ └── cost: 1360.04 + │ │ └── cost: 1390.34 │ └── [] │ ├── best: (project G2 G3 x) - │ └── cost: 1129.74 + │ └── cost: 1130.04 ├── G2: (ensure-distinct-on G4 G5 cols=(1)) (ensure-distinct-on G4 G5 cols=(1),ordering=+1) │ └── [] │ ├── best: (ensure-distinct-on G4="[ordering: +1]" G5 cols=(1),ordering=+1) - │ └── cost: 1099.73 + │ └── cost: 1100.03 ├── G3: (projections G6 G7) ├── G4: (left-join G8 G9 G10) (left-join G8 G9 G10) (right-join G9 G8 G10) (merge-join G8 G9 G11 left-join,+1,+6) (lookup-join G12 G11 kuvw@uvw,keyCols=[1 12],outCols=(1,6-8)) (lookup-join G13 G10 kuvw@vw,keyCols=[13],outCols=(1,6-8)) (right-join G9 G8 G10) (merge-join G8 G9 G11 left-join,+1,+6) (lookup-join G14 G11 kuvw@uvw,keyCols=[1 14],outCols=(1,6-8)) (lookup-join G15 G10 kuvw@vw,keyCols=[15],outCols=(1,6-8)) (merge-join G9 G8 G11 right-join,+6,+1) (merge-join G9 G8 G11 right-join,+6,+1) │ ├── [ordering: +1] │ │ ├── best: (merge-join G8="[ordering: +1]" G9="[ordering: +6 opt(7)]" G11 left-join,+1,+6) - │ │ └── cost: 1069.71 + │ │ └── cost: 1070.01 │ └── [] │ ├── best: (merge-join G8="[ordering: +1]" G9="[ordering: +6 opt(7)]" G11 left-join,+1,+6) - │ └── cost: 1069.71 + │ └── cost: 1070.01 ├── G5: (aggregations G16) ├── G6: (variable kuvw.w) ├── G7: (plus G17 G18) @@ -1753,7 +1753,7 @@ memo (optimized, ~36KB, required=[presentation: w:10] [ordering: +11,+1]) ├── G9: (select G19 G20) (scan kuvw@vw,cols=(6-8),constrained) │ ├── [ordering: +6 opt(7)] │ │ ├── best: (sort G9) - │ │ └── cost: 15.58 + │ │ └── cost: 15.88 │ └── [] │ ├── best: (scan kuvw@vw,cols=(6-8),constrained) │ └── cost: 14.71 diff --git a/pkg/sql/opt/xform/testdata/rules/join b/pkg/sql/opt/xform/testdata/rules/join index b8af2a8d8c90..dc093b249735 100644 --- a/pkg/sql/opt/xform/testdata/rules/join +++ b/pkg/sql/opt/xform/testdata/rules/join @@ -342,7 +342,7 @@ memo (optimized, ~37KB, required=[presentation: pid1:1,cid1:2,gcid1:3,gca1:4,ca1 ├── G8: (inner-join G10 G5 G14) (inner-join G5 G10 G14) (merge-join G10 G5 G12 inner-join,+6,+10) (lookup-join G10 G12 parent1,keyCols=[6],outCols=(6-8,10,11)) (merge-join G5 G10 G12 inner-join,+10,+6) (lookup-join G5 G12 child1,keyCols=[10],outCols=(6-8,10,11)) │ ├── [ordering: +(6|10),+7] │ │ ├── best: (sort G8) - │ │ └── cost: 2368.34 + │ │ └── cost: 2418.34 │ ├── [ordering: +(6|10)] │ │ ├── best: (merge-join G10="[ordering: +6]" G5="[ordering: +10]" G12 inner-join,+6,+10) │ │ └── cost: 2138.05 @@ -363,7 +363,7 @@ memo (optimized, ~37KB, required=[presentation: pid1:1,cid1:2,gcid1:3,gca1:4,ca1 ├── G11: (inner-join G7 G5 G6) (inner-join G5 G7 G6) (merge-join G7 G5 G12 inner-join,+1,+10) (lookup-join G7 G12 parent1,keyCols=[1],outCols=(1-4,10,11)) (merge-join G5 G7 G12 inner-join,+10,+1) (lookup-join G5 G12 grandchild1,keyCols=[10],outCols=(1-4,10,11)) │ ├── [ordering: +(1|10),+2] │ │ ├── best: (sort G11) - │ │ └── cost: 2388.34 + │ │ └── cost: 2448.34 │ ├── [ordering: +(1|10)] │ │ ├── best: (merge-join G7="[ordering: +1]" G5="[ordering: +10]" G12 inner-join,+1,+10) │ │ └── cost: 2158.05 @@ -543,7 +543,7 @@ memo (optimized, ~14KB, required=[presentation: a:1,b:2,c:3,v:6,s:7,t:8,u:9]) ├── G5: (values G10 id=v1) │ ├── [ordering: +6] │ │ ├── best: (sort G5) - │ │ └── cost: 0.12 + │ │ └── cost: 0.14 │ └── [] │ ├── best: (values G10 id=v1) │ └── cost: 0.03 @@ -1534,7 +1534,7 @@ memo (optimized, ~11KB, required=[presentation: a:1,b:2,c:3,x:6,y:7,z:8]) ├── G3: (scan xyz,cols=(6-8)) (scan xyz@xy,cols=(6-8)) (scan xyz@yz,cols=(6-8)) │ ├── [ordering: +8] │ │ ├── best: (sort G3) - │ │ └── cost: 1293.35 + │ │ └── cost: 1323.35 │ └── [] │ ├── best: (scan xyz,cols=(6-8)) │ └── cost: 1074.02 @@ -1562,7 +1562,7 @@ memo (optimized, ~10KB, required=[presentation: a:1,b:2,c:3,x:6,y:7,z:8]) ├── G3: (scan xyz,cols=(6-8)) (scan xyz@xy,cols=(6-8)) (scan xyz@yz,cols=(6-8)) │ ├── [ordering: +8] │ │ ├── best: (sort G3) - │ │ └── cost: 1293.35 + │ │ └── cost: 1323.35 │ └── [] │ ├── best: (scan xyz,cols=(6-8)) │ └── cost: 1074.02 @@ -1752,7 +1752,7 @@ memo (optimized, ~10KB, required=[presentation: a:1,b:2,c:3,x:6,y:7,z:8]) ├── G3: (scan xyz,cols=(6-8)) (scan xyz@xy,cols=(6-8)) (scan xyz@yz,cols=(6-8)) │ ├── [ordering: +8] │ │ ├── best: (sort G3) - │ │ └── cost: 1293.35 + │ │ └── cost: 1323.35 │ └── [] │ ├── best: (scan xyz,cols=(6-8)) │ └── cost: 1074.02 @@ -1792,7 +1792,7 @@ memo (optimized, ~12KB, required=[presentation: a:1,b:2,c:3,x:6,y:7,z:8]) ├── G2: (scan xyz,cols=(6-8)) (scan xyz@xy,cols=(6-8)) (scan xyz@yz,cols=(6-8)) │ ├── [ordering: +8] │ │ ├── best: (sort G2) - │ │ └── cost: 1293.35 + │ │ └── cost: 1323.35 │ └── [] │ ├── best: (scan xyz,cols=(6-8)) │ └── cost: 1074.02 diff --git a/pkg/sql/opt/xform/testdata/rules/join_order b/pkg/sql/opt/xform/testdata/rules/join_order index dba1d928b712..da468b58a640 100644 --- a/pkg/sql/opt/xform/testdata/rules/join_order +++ b/pkg/sql/opt/xform/testdata/rules/join_order @@ -561,14 +561,14 @@ memo (optimized, ~24KB, required=[presentation: b:1,x:2,c:4,y:5,d:7,z:8,a:10,b:1 ├── G2: (scan bx,cols=(1,2)) │ ├── [ordering: +2] │ │ ├── best: (sort G2) - │ │ └── cost: 1263.35 + │ │ └── cost: 1283.35 │ └── [] │ ├── best: (scan bx,cols=(1,2)) │ └── cost: 1044.02 ├── G3: (inner-join G6 G7 G8) (merge-join G6 G7 G5 inner-join,+5,+8) │ ├── [ordering: +(5|8|10)] │ │ ├── best: (merge-join G6="[ordering: +5]" G7="[ordering: +(8|10)]" G5 inner-join,+5,+8) - │ │ └── cost: 3758.54 + │ │ └── cost: 3798.54 │ └── [] │ ├── best: (inner-join G6 G7 G8) │ └── cost: 3339.84 @@ -577,14 +577,14 @@ memo (optimized, ~24KB, required=[presentation: b:1,x:2,c:4,y:5,d:7,z:8,a:10,b:1 ├── G6: (scan cy,cols=(4,5)) │ ├── [ordering: +5] │ │ ├── best: (sort G6) - │ │ └── cost: 1263.35 + │ │ └── cost: 1283.35 │ └── [] │ ├── best: (scan cy,cols=(4,5)) │ └── cost: 1044.02 ├── G7: (inner-join G10 G11 G12) (merge-join G10 G11 G5 inner-join,+8,+10) (lookup-join G10 G5 abc,keyCols=[8],outCols=(7,8,10-13)) │ ├── [ordering: +(8|10)] │ │ ├── best: (merge-join G10="[ordering: +8]" G11="[ordering: +10]" G5 inner-join,+8,+10) - │ │ └── cost: 2377.28 + │ │ └── cost: 2397.28 │ └── [] │ ├── best: (inner-join G10 G11 G12) │ └── cost: 2167.96 @@ -593,7 +593,7 @@ memo (optimized, ~24KB, required=[presentation: b:1,x:2,c:4,y:5,d:7,z:8,a:10,b:1 ├── G10: (scan dz,cols=(7,8)) │ ├── [ordering: +8] │ │ ├── best: (sort G10) - │ │ └── cost: 1263.35 + │ │ └── cost: 1283.35 │ └── [] │ ├── best: (scan dz,cols=(7,8)) │ └── cost: 1044.02 @@ -627,7 +627,7 @@ memo (optimized, ~52KB, required=[presentation: b:1,x:2,c:4,y:5,d:7,z:8,a:10,b:1 ├── G2: (scan bx,cols=(1,2)) │ ├── [ordering: +2] │ │ ├── best: (sort G2) - │ │ └── cost: 1263.35 + │ │ └── cost: 1283.35 │ └── [] │ ├── best: (scan bx,cols=(1,2)) │ └── cost: 1044.02 @@ -639,7 +639,7 @@ memo (optimized, ~52KB, required=[presentation: b:1,x:2,c:4,y:5,d:7,z:8,a:10,b:1 ├── G5: (scan cy,cols=(4,5)) │ ├── [ordering: +5] │ │ ├── best: (sort G5) - │ │ └── cost: 1263.35 + │ │ └── cost: 1283.35 │ └── [] │ ├── best: (scan cy,cols=(4,5)) │ └── cost: 1044.02 @@ -651,7 +651,7 @@ memo (optimized, ~52KB, required=[presentation: b:1,x:2,c:4,y:5,d:7,z:8,a:10,b:1 ├── G8: (inner-join G2 G5 G4) (inner-join G5 G2 G4) │ ├── [ordering: +(2|5)] │ │ ├── best: (sort G8) - │ │ └── cost: 5011.07 + │ │ └── cost: 5403.11 │ └── [] │ ├── best: (inner-join G2 G5 G4) │ └── cost: 2216.07 @@ -662,14 +662,14 @@ memo (optimized, ~52KB, required=[presentation: b:1,x:2,c:4,y:5,d:7,z:8,a:10,b:1 ├── G10: (scan dz,cols=(7,8)) │ ├── [ordering: +8] │ │ ├── best: (sort G10) - │ │ └── cost: 1263.35 + │ │ └── cost: 1283.35 │ └── [] │ ├── best: (scan dz,cols=(7,8)) │ └── cost: 1044.02 ├── G11: (inner-join G2 G14 G4) (inner-join G14 G2 G4) (inner-join G5 G16 G4) (inner-join G16 G5 G4) (inner-join G8 G18 G23) (inner-join G18 G8 G23) (lookup-join G8 G19 abc,keyCols=[5],outCols=(1,2,4,5,10-13)) (merge-join G18 G8 G19 inner-join,+10,+5) │ ├── [ordering: +(2|5|10)] - │ │ ├── best: (sort G11) - │ │ └── cost: 6134.84 + │ │ ├── best: (merge-join G18="[ordering: +10]" G8="[ordering: +(2|5)]" G19 inner-join,+10,+5) + │ │ └── cost: 6693.16 │ └── [] │ ├── best: (inner-join G2 G14 G4) │ └── cost: 3339.84 @@ -677,35 +677,35 @@ memo (optimized, ~52KB, required=[presentation: b:1,x:2,c:4,y:5,d:7,z:8,a:10,b:1 ├── G13: (inner-join G2 G10 G21) (inner-join G10 G2 G21) │ ├── [ordering: +(2|8)] │ │ ├── best: (sort G13) - │ │ └── cost: 5011.07 + │ │ └── cost: 5403.11 │ └── [] │ ├── best: (inner-join G2 G10 G21) │ └── cost: 2216.07 ├── G14: (inner-join G5 G18 G23) (inner-join G18 G5 G23) (lookup-join G5 G19 abc,keyCols=[5],outCols=(4,5,10-13)) (merge-join G18 G5 G19 inner-join,+10,+5) │ ├── [ordering: +(5|10)] │ │ ├── best: (merge-join G18="[ordering: +10]" G5="[ordering: +5]" G19 inner-join,+10,+5) - │ │ └── cost: 2377.28 + │ │ └── cost: 2397.28 │ └── [] │ ├── best: (inner-join G5 G18 G23) │ └── cost: 2167.96 ├── G15: (inner-join G5 G10 G7) (inner-join G10 G5 G7) │ ├── [ordering: +(5|8)] │ │ ├── best: (sort G15) - │ │ └── cost: 5011.07 + │ │ └── cost: 5403.11 │ └── [] │ ├── best: (inner-join G5 G10 G7) │ └── cost: 2216.07 ├── G16: (inner-join G2 G18 G25) (inner-join G18 G2 G25) (lookup-join G2 G19 abc,keyCols=[2],outCols=(1,2,10-13)) (merge-join G18 G2 G19 inner-join,+10,+2) │ ├── [ordering: +(2|10)] │ │ ├── best: (merge-join G18="[ordering: +10]" G2="[ordering: +2]" G19 inner-join,+10,+2) - │ │ └── cost: 2377.28 + │ │ └── cost: 2397.28 │ └── [] │ ├── best: (inner-join G2 G18 G25) │ └── cost: 2167.96 ├── G17: (inner-join G2 G15 G4) (inner-join G15 G2 G4) (inner-join G5 G13 G7) (inner-join G13 G5 G7) (inner-join G8 G10 G7) (inner-join G10 G8 G7) │ ├── [ordering: +(2|5|8)] │ │ ├── best: (sort G17) - │ │ └── cost: 38459.25 + │ │ └── cost: 44281.05 │ └── [] │ ├── best: (inner-join G15 G2 G4) │ └── cost: 4370.42 diff --git a/pkg/sql/opt/xform/testdata/rules/scan b/pkg/sql/opt/xform/testdata/rules/scan index 3f64ede1da7f..9673096daeaf 100644 --- a/pkg/sql/opt/xform/testdata/rules/scan +++ b/pkg/sql/opt/xform/testdata/rules/scan @@ -229,7 +229,7 @@ memo (optimized, ~2KB, required=[presentation: s:4,i:2,f:3] [ordering: +3]) └── G1: (scan a,cols=(2-4)) (scan a@s_idx,cols=(2-4)) ├── [presentation: s:4,i:2,f:3] [ordering: +3] │ ├── best: (sort G1) - │ └── cost: 1293.35 + │ └── cost: 1323.35 └── [] ├── best: (scan a@s_idx,cols=(2-4)) └── cost: 1074.02 @@ -241,7 +241,7 @@ memo (optimized, ~2KB, required=[presentation: s:4,i:2,f:3] [ordering: -4,+2]) └── G1: (scan a,cols=(2-4)) (scan a@s_idx,cols=(2-4)) ├── [presentation: s:4,i:2,f:3] [ordering: -4,+2] │ ├── best: (sort G1="[ordering: -4]") - │ └── cost: 1270.13 + │ └── cost: 1300.13 ├── [ordering: -4] │ ├── best: (scan a@s_idx,rev,cols=(2-4)) │ └── cost: 1173.68 @@ -284,7 +284,7 @@ memo (optimized, ~3KB, required=[presentation: d:4] [ordering: +6]) ├── G1: (project G2 G3 d) │ ├── [presentation: d:4] [ordering: +6] │ │ ├── best: (sort G1) - │ │ └── cost: 1293.36 + │ │ └── cost: 1313.36 │ └── [] │ ├── best: (project G2 G3 d) │ └── cost: 1074.03 @@ -361,7 +361,7 @@ memo (optimized, ~2KB, required=[presentation: i:2,k:1] [ordering: -4,+2,+1]) └── G1: (scan a,cols=(1,2,4)) (scan a@s_idx,cols=(1,2,4)) (scan a@si_idx,cols=(1,2,4)) ├── [presentation: i:2,k:1] [ordering: -4,+2,+1] │ ├── best: (sort G1="[ordering: -4]") - │ └── cost: 1174.79 + │ └── cost: 1204.79 ├── [ordering: -4] │ ├── best: (scan a@si_idx,cols=(1,2,4)) │ └── cost: 1074.02 diff --git a/pkg/sql/opt/xform/testdata/rules/select b/pkg/sql/opt/xform/testdata/rules/select index 972d636d4aaa..9efd06e71371 100644 --- a/pkg/sql/opt/xform/testdata/rules/select +++ b/pkg/sql/opt/xform/testdata/rules/select @@ -1085,15 +1085,16 @@ New expression 1 of 2: └── ordering: +1 opt(4) [actual: +1] New expression 2 of 2: - sort + index-join kifs ├── columns: s:4!null i:2 f:3 [hidden: k:1!null] ├── key: (1) ├── fd: ()-->(4), (1)-->(2,3) ├── ordering: +1 opt(4) [actual: +1] - └── index-join kifs - ├── columns: k:1!null i:2 f:3 s:4!null + └── sort + ├── columns: k:1!null i:2 s:4!null ├── key: (1) - ├── fd: ()-->(4), (1)-->(2,3) + ├── fd: ()-->(4), (1)-->(2) + ├── ordering: +1 opt(4) [actual: +1] └── scan kifs@si_idx ├── columns: k:1!null i:2 s:4!null ├── constraint: /-4/-2/1: [/'foo' - /'foo'] @@ -1109,14 +1110,14 @@ memo (optimized, ~6KB, required=[presentation: s:4,i:2,f:3] [ordering: +2 opt(4) ├── G1: (select G2 G3) (scan kifs@s_idx,cols=(2-4),constrained) (index-join G4 kifs,cols=(2-4)) │ ├── [presentation: s:4,i:2,f:3] [ordering: +2 opt(4)] │ │ ├── best: (sort G1) - │ │ └── cost: 15.58 + │ │ └── cost: 15.88 │ └── [] │ ├── best: (scan kifs@s_idx,cols=(2-4),constrained) │ └── cost: 14.71 ├── G2: (scan kifs,cols=(2-4)) (scan kifs@s_idx,cols=(2-4)) │ ├── [ordering: +2 opt(4)] │ │ ├── best: (sort G2) - │ │ └── cost: 1293.35 + │ │ └── cost: 1323.35 │ └── [] │ ├── best: (scan kifs@s_idx,cols=(2-4)) │ └── cost: 1074.02