<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                [TOC] # 分區裁剪 當用戶訪問分區表時,往往只需要訪問其中部分的分區,所以通過優化器避免訪問無關分區的優化過程我們稱之為分區裁剪((Partition Pruning)。分區裁剪是分區表提供的重要優化手段,通過分區的裁剪,SQL 的執行效率可以得到大幅度的提升。您可以利用分區裁剪的特性,在訪問中加入定位分區的條件,避免訪問無關數據,優化查詢性能。 分區裁剪本身是一個比較復雜的過程,優化器需要根據用戶表的分區信息和 SQL 中給定的條件,抽取出相關的分區信息。由于 SQL 中的條件往往比較復雜,整個抽取邏輯的復雜性也隨之增加,這一過程由 OceanBase 數據庫中的 Query Range 子模塊完成。 以下示例中當用戶使用如下 SQL 訪問分區表時,由于 c1 為 1 的數據全部處于第 1 號分區(p1),實際上我們只需要訪問該分區即可(避免訪問第 0、2、3、4 號分區): ~~~ obclient> CREATE TABLE t1 ( c1 INT, c2 INT ) PARTITION BY HASH(c1) partitions 5; obclient> SELECT * FROM t1 WHERE c1 = 1; ~~~ 通過`EXPLAIN`查看執行計劃可以看到分區裁剪的結果: ~~~ obclient> EXPLAIN SELECT * FROM t1 WHERE c1 = 1 \G *************************** 1. row *************************** Query Plan: =================================== |ID|OPERATOR |NAME|EST. ROWS|COST| ----------------------------------- |0 |TABLE SCAN|t1 |1 |1303| =================================== Outputs & filters: ------------------------------------- 0 - output([t1.c1], [t1.c2]), filter([t1.c1 = 1]), access([t1.c1], [t1.c2]), partitions(p1) ~~~ ## 一級分區裁剪的基本原理 **Hash/List 分區** 分區裁剪就是根據`where`子句里面的條件并且計算得到分區列的值,然后通過結果判斷需要訪問哪些分區。如果分區函數為表達式,且該表達式作為一個整體出現在等值條件里,也可以做分區裁剪。 示例如下: ~~~ obclient> CREATE TABLE t1 ( c1 INT, c2 INT ) PARTITION BY HASH(c1 + c2) partitions 5; obclient> EXPLAIN SELECT * FROM t1 WHERE c1 + c2 = 1 \G *************************** 1. row *************************** Query Plan: =================================== |ID|OPERATOR |NAME|EST. ROWS|COST| ----------------------------------- |0 |TABLE SCAN|t1 |5 |1303| =================================== Outputs & filters: ------------------------------------- 0 - output([t1.c1], [t1.c2]), filter([t1.c1 + t1.c2 = 1]), access([t1.c1], [t1.c2]), partitions(p1) ~~~ **Range 分區** 通過`where`子句的分區鍵的范圍跟表定義的分區范圍的交集來確定需要訪問的分區。對于 Range 分區,因為考慮到函數的單調性,如果分區表達式是一個函數并且查詢條件是一個范圍,則不支持分區裁剪。 下述示例中,分區條件為表達式,而查詢條件為非等值條件(c1 100),則無法進行分區裁剪: ~~~ obclient> CREATE TABLE t1 ( c1 INT, c2 INT ) PARTITION BY RANGE(c1 + 1) ( PARTITION p0 VALUES less than (100), PARTITION p1 VALUES less than (200) ); obclient> EXPLAIN SELECT * FROM t1 WHERE c1 < 150 and c1 > 110 \G *************************** 1. row *************************** Query Plan: ============================================ |ID|OPERATOR |NAME|EST. ROWS|COST| -------------------------------------------- |0 |EXCHANGE IN DISTR | |19 |1410| |1 | EXCHANGE OUT DISTR| |19 |1303| |2 | TABLE SCAN |t1 |19 |1303| ============================================ Outputs & filters: ------------------------------------- 0 - output([t1.c1], [t1.c2]), filter(nil) 1 - output([t1.c1], [t1.c2]), filter(nil) 2 - output([t1.c1], [t1.c2]), filter([t1.c1 < 150], [t1.c1 > 110]), access([t1.c1], [t1.c2]), partitions(p[0-1]) ~~~ 如果查詢條件是等值條件,則可以進行分區裁剪。示例如下: ~~~ obclient> EXPLAIN SELECT * FROM t1 WHERE c1 = 150 \G *************************** 1. row *************************** Query Plan: =================================== |ID|OPERATOR |NAME|EST. ROWS|COST| ----------------------------------- |0 |TABLE SCAN|t1 |1 |1303| =================================== Outputs & filters: ------------------------------------- 0 - output([t1.c1], [t1.c2]), filter([t1.c1 = 150]), access([t1.c1], [t1.c2]), partitions(p1) ~~~ ## 二級分區裁剪的基本原理 對于二級分區,先按照一級分區鍵確定一級需要訪問的分區,然后在通過二級分區鍵確定二級分區需要訪問的分區。然后做一個乘積確定二級分區訪問的所有物理分區。 以下示例中,經過計算得到一級分區裁剪結果是 p1、p2,而二級分區裁剪的結果是 sp1,所以訪問的物理分區為 p1sp1 和 p2sp1: ~~~ obclient> CREATE TABLE t1 ( c1 INT , c2 INT ) PARTITION BY hash(c1) SUBPARTITION BY RANGE(c2) SUBPARTITION template ( SUBPARTITION sp0 VALUES less than(100), SUBPARTITION sp1 VALUES less than(200) ) partitions 5 SELECT * FROM t1 WHERE (c1 = 1 OR c1 = 2) AND (c2 > 101 AND c2 < 150) obclient> EXPLAIN SELECT * FROM t1 WHERE (c1 = 1 or c1 = 2) and (c2 > 101 and c2 < 150) \G *************************** 1. row *************************** Query Plan: ============================================ |ID|OPERATOR |NAME|EST. ROWS|COST| -------------------------------------------- |0 |EXCHANGE IN DISTR | |1 |1403| |1 |EXCHANGE OUT DISTR| |1 |1303| |2 | TABLE SCAN |t1 |1 |1303| ============================================ Outputs & filters: ------------------------------------- 0 - output([t1.c1], [t1.c2]), filter(nil) 1 - output([t1.c1], [t1.c2]), filter(nil) 2 - output([t1.c1], [t1.c2]), filter([t1.c1 = 1 OR t1.c1 = 2], [t1.c2 > 101], [t1.c2 < 150]), access([t1.c1], [t1.c2]), partitions(p1sp1, p2sp1) ~~~ 某些場景下,分區裁剪可能會存在一定程度的放大,但優化器可以確保裁剪的結果是所需訪問數據的超集,不會存在丟失數據的情況。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看