建议查询优化工具的计划

时间:2018-04-12 06:41:24

标签: mysql database postgresql innodb psql

有时我可以使用强制索引选项在查询上使用特定索引来加快查询速度。

然后经过一段时间后,该表中的数据可能会发生变化。我使用的力索引可能不是该查询的正确索引搜索。

我的问题是

  • 无论如何,建议查询优化器在其计划生成期间使用强制索引作为可能的选项。如果使用强制索引是一个缓慢的计划,那么它可以使用正常的查询计划。

  • 或者否则无论如何都要编辑MySql / PSQL代码以建议Optimiser在其计划生成期间使用强制索引作为可能的选项。

其他信息:我想将我的计划添加到优化计划列表中(Optimiser已经为查询创建了许多计划)。因此,在为查询选择最佳计划时,我希望优化人员也考虑我的计划。如果这种方式可行,那么优化器不需要每次都考虑强制索引。它可以将力指数作为计划生成的可能选项

据我所知,我试图澄清问题。如果有人无法理解您的查询评论。

6 个答案:

答案 0 :(得分:7)

唯一的方法是从查询中删除FORCE INDEX

您可以覆盖优化程序的计划,否则您可以让优化程序选择计划。

优化器无法判断使用索引是否会很慢。它试图在选择一个快速的计划时做出最好的猜测。

优化器可以更准确的唯一方法是运行两个查询,并比较性能差异,然后运行快速查询。这显然不实用,因此优化器旨在根据某些统计模型估算查询的成本。大部分时间这都是准确的,优化者的选择是最好的。

答案 1 :(得分:6)

您正在处理的一般概念是"内部数据库统计" (不是官方用语)。也就是说,数据库引擎用于制定查询计划的信息。统计信息存储详细信息,如索引中的密钥分配,表行大小,计数,空行百分比,数据清晰度等。

出于历史(和相关)性能原因,内部数据库统计信息不会即时更新,但通常会在DBA的要求下定期更新。在Postgres土地上,这些信息可以通过pg_statistic表格简洁地获得。不幸的是,MySQL并没有提供这些信息,但你可以从INFORMATION_SCHEMA和SHOW INDEXES中看到你可以收集到的信息。

对于您手头的问题 - 查询计划提示的短暂用处 - 是DB的统计数据不代表表数据。一般的响应是:更新数据库的相关表统计信息,您不需要在查询中提供优化程序提示:

ANALYZE TABLE <table_name>;

有一些需要注意的注意事项:

  • 如果没有额外的措施,数据库引擎的这种分析是短暂的:它不会在数据库重启/重启时持续存在。选项是在数据库启动时重新分析表,或者查看statistics persistence

  • 这会通过采样数据生成统计信息 - 查看随机表行的子集。本质上,随机抽样意味着在任何特定运行中收集的统计信息可能不是实际数据的良好表示,从而导致查询计划不佳。您可以通过innodb_stats_persistent_sample_pages

  • 增加示例页数
  • ANALYZE不是OPTIMIZE,您的表格也可能需要优化。 OPTIMIZE是一项昂贵的操作,需要锁定桌面,但在某些条件下可能非常有用。

  • ANALYZE是特定于表格的,无法弥补糟糕的表格布局。例如,我最近的任务是加速一组缓慢运行的报告查询。罪魁祸首?模式将时间和日期列存储为字符串,而不是本机数据类型。这具有重大意义,因为查询首先必须在比较之前将字符串转换为日期(包括数据中的错误),从而导致多个整个表扫描。非常糟糕。

  • ANALYZE无法弥补不良查询。例如,与前一个项目符号点一样,类似WHERE SOME_FUNCTION( col ) > some_value的内容意味着查询计划程序可能无法使用索引,因为每行必须首先执行FUNCTION以获取条件结果。并非总是如此,但经常在天真的SQL查询中找到。

  • ANALYZE无法弥补不良的正常化。不能承受潜在的大算法常数,通过适当的规范化,您将获得更大的大O算法胜利。

  • ANALYZE 创建索引。如果查询访问具有高基数但没有索引的列,则太糟糕了。知道根据已知或预期的查询将索引放在哪些列上取决于DBA。

像往常一样,在这些情况下,将所有StackOverflow建议与盐一起使用:您负责数据或程序,并在您面前拥有实际运行的产品。你可以测试,你可以测量,你可以四处寻找。我们不能。

答案 2 :(得分:5)

FORCE INDEX今天可能会很好,但明天会很糟糕。这是因为数据分布发生变化和/或查询中的常量发生变化。

有一些模式往往导致选择“错误”的指数:

SELECT ...
    WHERE ...
    ORDER BY ...

目前尚不清楚是针对WHERE还是针对ORDER BY进行优化。

SELECT ...
    FROM a
    JOIN b ON ...
    WHERE a.x ...
      AND b.y ...

并不清楚是先过滤a.x还是b.y。 (它不能同时对两者进行过滤。)

如果您提供特定查询,我们可能会提供特定提示。

有时,可以重新构造查询以欺骗优化器采用一条路径而不是另一条路径。版本8.0有许多“提示”,但不一定比FORCE INDEX更好。 STRAIGHT_JOIN是另一种暗示。

重新构造查询可能涉及将其中的一部分转换为子查询。但同样,你冒着“今天好,明天坏”的风险。

如果您“过度规范化”(例如规范化日期时间,然后使用BETWEEN),则解决方案可能涉及非规范化。

您使用的是'复合'索引吗?索引中WHERE的“范围”部分是最后一部分吗? (还有很多其他问题 - 让我们看一下具体的问题。)

答案 3 :(得分:5)

据我所知,

Mysql不足以支持您的需求,因为缺少某种统计和机制,例如直方图,动态采样等。

因此,如果数据发生变化,虽然及时收集统计信息,缺少前面描述的必要内容,但优化器可能没有按预期行为。

你的两个问题可能是一个好习惯,但对最终用户来说很难。

或者您可以为oracle或maria db团队提供建议吗?

答案 4 :(得分:5)

问:无论如何,建议查询优化器在其计划生成期间使用强制索引作为可能的选项。如果使用强制索引是一个缓慢的计划,那么它可以使用正常的查询计划。

答:不会。优化器会根据其给定的内容完成它的工作。优化器不会忽略提示。 SQL文本中包含的任何提示都会产生影响。

这就是为什么提示是“最后的手段”。我们的偏好是让优化器选择合适的计划。实现这一目标的最佳方法是仔细编写SQL以避免使用阻止使用适当索引的构造(例如,在函数中包装列),使合适的索引可用,并确保统计信息是准确的并且最多日期。

问:无论如何编辑MySql / PSQL代码以建议Optimiser在计划生成期间使用强制索引作为可能的选项吗?

答:优化程序将考虑所有索引,如果候选访问计划具有最低的成本估算,则选择使用特定索引。这不需要FORCE INDEX提示; MySQL将考虑索引。

在SQL文本中使用提示是最后的选择。在我们考虑使用提示(FORCE INDEX或其他)之前,我们应该

  • 使用允许(不阻止)使用适当索引的SQL结构。例如,对于DATETIME列dt,MySQL可以对此dt >= '2018-04-22' AND dt < '2018-04-23'使用范围扫描操作,但不能对此DATE(dt) = '2018-04-22'使用范围扫描操作。有时可以通过对SQL文本进行一些简单的调整来解决查询性能问题。有时会进行更广泛的重新设计和重写。

  • 有合适的索引可用(例如,考虑具有适当前导列的复合索引,并删除单行列上的冗余索引)

  • 确保统计数据是最新的并且代表表格(请注意,InnoDB使用一小部分页面收集统计数据。如果获取的页面不能代表表格,我们可以获得统计数据倾斜。

答案 5 :(得分:0)

我的问题是,你是否因为力量指数而经历过缓慢执行?

如果没有,
选择优化器。它会在糟糕的情况下跳过强制索引
  例如:select last_name from employees force index(idx_last_name) order by last_name;
在上面的查询中,它跳过强制索引

如果是,

您可以根据观察结果覆盖优化程序的计划。