• 允许每个分支使用不同的索引来加速查询。
    1. --- 如果不进行or-expansion的改写,该查询只能使用主表访问路径
    2. OceanBase (root@test)> explain select/*+NO_REWRITE()*/ * from t1 where t1.a = 1 or t1.b = 1;
    3. +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    4. | Query Plan |
    5. +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    6. | ===================================
    7. |ID|OPERATOR |NAME|EST. ROWS|COST|
    8. -----------------------------------
    9. |0 |TABLE SCAN|t1 |4 |649 |
    10. ===================================
    11. Outputs & filters:
    12. -------------------------------------
    13. 0 - output([t1.a], [t1.b], [t1.c], [t1.d], [t1.e]), filter([t1.a = 1 OR t1.b = 1]),
    14. access([t1.a], [t1.b], [t1.c], [t1.d], [t1.e]), partitions(p0)
    15. --- 改写之后,每个子查询能使用不同的索引访问路径
    16. OceanBase (root@test)> explain select * from t1 where t1.a = 1 or t1.b = 1;
    17. +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    18. | Query Plan |
    19. +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    20. | =========================================
    21. |ID|OPERATOR |NAME |EST. ROWS|COST|
    22. -----------------------------------------
    23. |0 |UNION ALL | |3 |190 |
    24. |1 | TABLE SCAN|t1(idx_a)|2 |94 |
    25. |2 | TABLE SCAN|t1(idx_b)|1 |95 |
    26. =========================================
    27. Outputs & filters:
    28. -------------------------------------
    29. 0 - output([UNION(t1.a, t1.a)], [UNION(t1.b, t1.b)], [UNION(t1.c, t1.c)], [UNION(t1.d, t1.d)], [UNION(t1.e, t1.e)]), filter(nil)
    30. 1 - output([t1.a], [t1.b], [t1.c], [t1.d], [t1.e]), filter(nil),
    31. access([t1.a], [t1.b], [t1.c], [t1.d], [t1.e]), partitions(p0)
    32. 2 - output([t1.a], [t1.b], [t1.c], [t1.d], [t1.e]), filter([lnnvl(t1.a = 1)]),
    33. access([t1.a], [t1.b], [t1.c], [t1.d], [t1.e]), partitions(p02
    • 允许每个分支使用不同的连接算法来加速查询,避免使用笛卡尔连接。
    1. OceanBase (root@test)> create table t1(a int, b int);
    2. Query OK, 0 rows affected (0.17 sec)
    3. OceanBase (root@test)> create table t2(a int, b int);
    4. Query OK, 0 rows affected (0.13 sec)
    5. OceanBase (root@test)> explain select/*+NO_REWRITE()*/ * from t1, t2 where t1.a = t2.a or t1.b = t2.b;
    6. |ID|OPERATOR |NAME|EST. ROWS|COST |
    7. -------------------------------------------
    8. |0 |NESTED-LOOP JOIN| |3957 |585457|
    9. |1 | TABLE SCAN |t1 |1000 |499 |
    10. |2 | TABLE SCAN |t2 |4 |583 |
    11. ===========================================
    12. Outputs & filters:
    13. -------------------------------------
    14. 0 - output([t1.a], [t1.b], [t2.a], [t2.b]), filter(nil),
    15. conds(nil), nl_params_([t1.a], [t1.b])
    16. 1 - output([t1.a], [t1.b]), filter(nil),
    17. access([t1.a], [t1.b]), partitions(p0)
    18. 2 - output([t2.a], [t2.b]), filter([? = t2.a OR ? = t2.b]),
    19. access([t2.a], [t2.b]), partitions(p0)
    20. ---被改写之后,每个子查询都使用了hash join
    21. OceanBase (root@test)> explain select * from t1, t2 where t1.a = t2.a or t1.b = t2.b;
    22. |ID|OPERATOR |NAME|EST. ROWS|COST|
    23. -------------------------------------
    24. |0 |UNION ALL | |2970 |9105|
    25. |1 | HASH JOIN | |1980 |3997|
    26. |2 | TABLE SCAN|t1 |1000 |499 |
    27. |3 | TABLE SCAN|t2 |1000 |499 |
    28. |4 | HASH JOIN | |990 |3659|
    29. |5 | TABLE SCAN|t1 |1000 |499 |
    30. |6 | TABLE SCAN|t2 |1000 |499 |
    31. =====================================
    32. Outputs & filters:
    33. -------------------------------------
    34. 0 - output([UNION(t1.a, t1.a)], [UNION(t1.b, t1.b)], [UNION(t2.a, t2.a)], [UNION(t2.b, t2.b)]), filter(nil)
    35. 1 - output([t1.a], [t1.b], [t2.a], [t2.b]), filter(nil),
    36. equal_conds([t1.a = t2.a]), other_conds(nil)
    37. 2 - output([t1.a], [t1.b]), filter(nil),
    38. access([t1.a], [t1.b]), partitions(p0)
    39. 3 - output([t2.a], [t2.b]), filter(nil),
    40. access([t2.a], [t2.b]), partitions(p0)
    41. 4 - output([t1.a], [t1.b], [t2.a], [t2.b]), filter(nil),
    42. equal_conds([t1.b = t2.b]), other_conds([lnnvl(t1.a = t2.a)])
    43. 5 - output([t1.a], [t1.b]), filter(nil),
    44. access([t2.a], [t2.b]), partitions(p0)
    • 允许每个分支分别消除排序,更加快速的获取top-k结果。
    1. OceanBase (root@test)> create table t1(a int, b int, index idx_a(a, b));
    2. Query OK, 0 rows affected (0.20 sec)
    3. ---不改写的话,需要排序最终获取top-k结果
    4. OceanBase (root@test)> explain select/*+NO_REWRITE()*/ * from t1 where t1.a = 1 or t1.a = 2 order by b limit 10;
    5. | ==========================================
    6. |ID|OPERATOR |NAME |EST. ROWS|COST|
    7. ------------------------------------------
    8. |0 |LIMIT | |4 |77 |
    9. |1 | TOP-N SORT | |4 |76 |
    10. |2 | TABLE SCAN|t1(idx_a)|4 |73 |
    11. ==========================================
    12. Outputs & filters:
    13. -------------------------------------
    14. 0 - output([t1.a], [t1.b]), filter(nil), limit(10), offset(nil)
    15. 1 - output([t1.a], [t1.b]), filter(nil), sort_keys([t1.b, ASC]), topn(10)
    16. 2 - output([t1.a], [t1.b]), filter(nil),
    17. access([t1.a], [t1.b]), partitions(p0)
    18. --- 进行改写的话,排序算子可以被消除,最终获取top-k结果
    19. OceanBase (root@test)> explain select * from t1 where t1.a = 1 or t1.a = 2 order by b limit 10;
    20. | ===========================================
    21. |ID|OPERATOR |NAME |EST. ROWS|COST|
    22. -------------------------------------------
    23. |0 |LIMIT | |3 |76 |
    24. |1 | TOP-N SORT | |3 |76 |
    25. |2 | UNION ALL | |3 |74 |
    26. |3 | TABLE SCAN|t1(idx_a)|2 |37 |
    27. |4 | TABLE SCAN|t1(idx_a)|1 |37 |
    28. ===========================================
    29. Outputs & filters:
    30. -------------------------------------
    31. 0 - output([UNION(t1.a, t1.a)], [UNION(t1.b, t1.b)]), filter(nil), limit(10), offset(nil)
    32. 1 - output([UNION(t1.a, t1.a)], [UNION(t1.b, t1.b)]), filter(nil), sort_keys([UNION(t1.b, t1.b), ASC]), topn(10)
    33. 2 - output([UNION(t1.a, t1.a)], [UNION(t1.b, t1.b)]), filter(nil)
    34. 3 - output([t1.a], [t1.b]), filter(nil),
    35. access([t1.a], [t1.b]), partitions(p0),
    36. limit(10), offset(nil)
    37. 4 - output([t1.a], [t1.b]), filter([lnnvl(t1.a = 1)]),