建议计划查询优化器

hmae6n7t  于 2021-06-24  发布在  Mysql
关注(0)|答案(6)|浏览(273)

有时我可以使用forceindex选项在查询上使用特定索引,以加快查询速度。
过了一段时间,表中的数据可能会改变。我使用的force索引可能不是该查询的正确索引搜索。
我的问题是
无论如何,是否有建议查询优化程序在其计划生成期间使用强制索引作为可能的选项。如果使用强制索引的计划很慢,那么可以使用普通的查询计划。
或者无论如何都要编辑mysql/psql的代码,以建议优化人员在计划生成期间使用force索引作为可能的选项。
附加信息:我想把我的计划添加到优化器计划列表中(优化器已经为一个查询创建了许多计划)。因此,在为查询选择最佳计划时,我希望乐观主义者也考虑我的计划。如果这种方法可行,那么优化者不必每次都考虑力指数。它可以将力指数作为生成计划的一个可能选项
据我所知,我试图把这个问题说清楚。如果有人不能理解你的问题。

jecbmhm3

jecbmhm31#

据我所知,
mysql不足以支持您的需求,因为它缺乏某种统计和机制,例如直方图、动态采样等。
因此,如果数据发生了变化,尽管及时收集了统计数据,但缺少前面描述的必要内容,优化器可能不会像您预期的那样工作。
你的两个问题可能是很好的练习,但对最终用户来说很难。
或者你可以给oracle或maria db团队提供建议?

wqnecbli

wqnecbli2#

唯一的办法就是 FORCE INDEX 从你的询问中。
您可以覆盖优化器的计划,或者让优化器选择计划。
优化器无法判断使用索引是否会很慢。它试图做出最好的猜测来选择一个快速的计划。
优化器能够更精确的唯一方法是运行两个查询,比较性能差异,然后运行快速查询。这显然是不实际的,因此优化器是基于某种统计模型来估计查询的成本的。大多数情况下,这是足够准确的,优化器的选择是最好的。

vof42yt1

vof42yt13#

问:有没有建议查询优化程序在生成计划时使用force索引作为可能的选项。如果使用强制索引的计划很慢,那么可以使用普通的查询计划。
答:不,优化器做的就是它所做的事情。优化器不会忽略提示。sql文本中包含的任何提示都会产生影响。
这就是为什么暗示是“最后的手段”。我们的偏好是让优化器选择一个合适的计划。实现这一点的最佳方法是小心地编写sql,以避免使用妨碍适当索引的构造(例如,在函数中 Package 列),使适当的索引可用,并确保统计信息是准确的和最新的。
问:是否有必要编辑mysql/psql的代码,以建议优化人员在计划生成期间使用force索引作为可能的选项?
答:优化器将考虑所有索引,如果候选访问计划的成本估计最低,则选择使用特定索引。这不需要强制索引提示;mysql将考虑索引。
在sql文本中使用提示是最后的手段。在考虑使用提示(强制索引或其他)之前,我们应该
使用允许(但不阻止)使用适当索引的sql构造。例如,使用datetime列 dt ,mysql可以对此使用范围扫描操作 dt >= '2018-04-22' AND dt < '2018-04-23' 但不是为了这个 DATE(dt) = '2018-04-22' . 有时可以通过对sql文本进行一些简单的调整来解决查询性能问题。有时需要更广泛的重新设计和重新编写。
有合适的索引可用(例如,考虑具有适当前导列的复合索引,并删除单例列上的冗余索引)
确保统计数据是最新的,并且是表的代表(注意innodb使用一个小的页面样本收集统计数据。如果采样的页面不能代表表,我们可以得到倾斜的统计数据。

cczfrluj

cczfrluj4#

您处理的一般概念是“内部数据库统计”(不是官方术语)。也就是说,数据库引擎用于制定查询计划的信息。统计信息存储索引中的键分布、表行大小、计数、空行百分比、数据的显著性等详细信息。
出于历史(和相关的)性能原因,内部数据库统计信息不会动态更新,但通常会根据dba的要求定期更新。在postgres land,这些信息可以通过 pg_statistic table。不幸的是,mysql并没有提供这些信息,但是您可以看到您可以从信息模式中收集到什么并显示索引。
您手头的问题是——查询计划提示的短暂有用性——db的统计数据不能代表表数据。一般的回答是:更新数据库中有问题的表的统计信息,这样就不需要在查询中提供优化器提示了:

ANALYZE TABLE <table_name>;

有一些注意事项需要注意:
如果没有额外的措施,db引擎的这种分析是短暂的:它不会在数据库重新启动/重新启动期间持续存在。选项是在db启动时重新分析表,或者查看统计持久性。
它通过对数据进行采样(查看随机表行的子集)来生成统计信息。从本质上讲,随机抽样意味着,在任何特定的运行中,收集的统计数据都可能无法很好地表示实际数据,从而导致糟糕的查询计划。您可以通过
innodb_stats_persistent_sample_pages ANALYZE 不是 OPTIMIZE ,并且您的表可能还需要优化。 OPTIMIZE 是一个昂贵的操作,需要在表上加锁,但在某些条件下可能非常有益。 ANALYZE 是特定于表的,不能弥补表布局的不足。例如,我最近的任务是加速一组运行缓慢的报表查询。罪魁祸首?模式将时间和日期列存储为字符串,而不是本机数据类型。这会产生巨大的影响,因为查询首先必须在比较之前将字符串转换为日期(包括数据中的错误),从而导致多个整表扫描。非常糟糕。 ANALYZE 无法弥补糟糕的查询。例如,与前面的要点一样 WHERE SOME_FUNCTION( col ) > some_value 这意味着查询规划器可能无法利用索引,因为每行必须首先执行函数才能获得条件结果。不总是这样,但通常在幼稚的sql查询中可以找到。 ANALYZE 无法弥补标准化的不足。尽管算法常数可能很大,但通过适当的规范化,您将获得更大的big-o算法胜利。 ANALYZE 不创建索引。如果查询访问具有高基数但没有索引的列,那就太糟糕了。dba需要知道根据已知或预期的查询在哪些列上放置索引。
像往常一样,在这样的情况下,把所有的建议都说得一清二楚:你是数据或程序的负责人,实际运行的产品就在你面前。你可以测试,你可以测量,你可以到处看看。我们不能。

xqk2d5yq

xqk2d5yq5#

我的问题是,你有没有因为力指数而经历过执行缓慢的经历?
如果没有,
按照优化器的选择。在恶劣的情况下它会跳过力指数
前任: select last_name from employees force index(idx_last_name) order by last_name; 在上面的查询中,它跳过了force索引
如果是,
您可以基于您的观察覆盖优化器的计划。

kuarbcqp

kuarbcqp6#

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 是另一种暗示。
重新格式化查询可能需要将查询的一部分转换为子查询。不过,你又冒着“今天好,明天坏”的风险。
如果您有“过度规范化”(例如规范化datetime,那么使用 BETWEEN ),解决方案可能涉及反规范化。
你用的是“复合”索引吗?“范围”是 WHERE 索引中的最后一个(还有很多其他问题——让我们看看具体的查询。)

相关问题