Optimizer Hints¶
当你确定了执行计划所存在的问题时,比如优化器选择的不是最优查询计划时,可以使用 Optimizer Hints 来控制执行计划的生成。
Hint 提示指令告诉查询优化器如何执行查询语句。通过使用提示,可以为查询提供有关如何访问数据的信息,以提高查询的性能。Hint 提示指令通常用于调优大型或复杂的查询。
提示可以用于修改查询的执行计划,包括选择不同的索引、使用不同的 JOIN 算法或改变连接顺序等。
SQL 中的提示使用注释语法,可以在查询语句中添加特定的注释来指定提示。
语法格式¶
{DELETE|INSERT|SELECT|UPDATE} /*+ hint [text] [hint[text]]... */
语法解释¶
DELETE、INSERT、SELECT、UPDATE是 SQL 语句的关键字。/*+ */是 SQL 语句中的注释符号。hint是提示的具体指令。text是提示指令的参数。
以下是一些常用的 SQL 提示:
/*+ INDEX (table index) */:指定使用特定的索引来执行查询。
/*+ FULL (table) */:指定执行全表扫描而不是使用索引。
应用场景¶
查询优化器选择不合适的执行计划时,可以使用
hint提示来指定一个更好的执行计划。例如,当查询涉及多个表时,优化器可能会选择错误的连接算法或连接顺序,从而导致查询的性能下降。在这种情况下,可以使用提示来指定一个更好的连接算法或连接顺序。当查询包含复杂的子查询或聚合函数时,可以使用
hint提示来优化查询的执行计划。由于优化器无法分析复杂的子查询或聚合函数,因此可能会选择错误的执行计划,从而导致查询的性能下降。当查询访问的数据量非常大时,可以使用
hint提示来优化查询的执行计划。在这种情况下,可以使用提示来指定使用特定的索引或连接算法,以提高查询的性能。
MatrixOne 支持使用 hint 提示用于选择全表扫描或使用索引扫描,以及优化多表连接的顺序。
选择全表扫描或使用索引扫描:
使用索引扫描可以加快查询的速度,但在某些情况下,全表扫描可能比使用索引扫描更快。例如,当查询条件过于宽泛时,使用索引可能会变得比较缓慢。在这种情况下,可以使用以下提示语法来选择使用全表扫描或索引扫描:
SELECT /*+ INDEX(table_name index_name) */ column_name FROM table_name WHERE ...
其中,table_name 是表名,index_name 是索引名,column_name 是列名。如果指定了索引名,则查询将使用该索引进行扫描。如果没有指定索引名,则查询将使用全表扫描。
优化多表连接的顺序:
当查询涉及多个表时,查询优化器将尝试选择最优的连接顺序。但在某些情况下,优化器可能无法选择最优的连接顺序,从而导致查询的性能下降。在这种情况下,可以使用以下提示语法来优化多表连接的顺序:
SELECT /*+ ORDERED */ column_name FROM table1, table2 WHERE table1.column1 = table2.column2;
其中,ORDERED 指定了查询应按照表的顺序连接,即先连接 table1,再连接 table2。这样可以避免优化器选择错误的连接顺序,从而提高查询的性能。
示例¶
-- 新建一个 名为 orders 的表
CREATE TABLE order (
order_id INT PRIMARY KEY,
customer_id INT,
order_date DATE,
order_total DECIMAL(10, 2)
);
-- 插入数据
INSERT INTO order (order_id, customer_id, order_date, order_total)
VALUES
(1, 101, '2022-05-10', 100.00),
(2, 102, '2022-05-09', 150.00),
(3, 103, '2022-05-08', 200.00),
(4, 104, '2022-05-07', 50.00);
-- 查询某个客户的所有订单,并按订单日期降序排列
SELECT order_id, order_date, order_total
FROM orders
WHERE customer_id = 123
ORDER BY order_date DESC;
为了优化这个查询,我们可以使用以下 hint 提示:
-- 使用名为 idx_customer_id 的索引来执行查询,这个索引是基于 customer_id 字段创建的
SELECT /*+ INDEX(orders idx_customer_id) */ order_id, order_date, order_total
FROM orders
WHERE customer_id = 123
ORDER BY order_date DESC;
限制¶
当前 /*+ HINT_NAME(t1, t2) */ 仅语法实现,暂无法控制执行计划。
另请参阅¶
enable_remap_hint:一个系统变量,用于启用查询重写提示功能,允许你通过 JSON 格式的注释将表名映射到自定义的 SELECT 查询。