vin*_*eth 10 mysql database postgresql innodb psql
有时我可以使用强制索引选项在查询上使用特定索引来加快查询速度.
然后经过一段时间后,该表中的数据可能会发生变化.我使用的力索引可能不是该查询的正确索引搜索.
我的问题是
无论如何,建议查询优化器在其计划生成期间使用强制索引作为可能的选项.如果使用强制索引是一个缓慢的计划,那么它可以使用正常的查询计划.
或者否则无论如何都要编辑MySql/PSQL代码以建议Optimiser在其计划生成期间使用强制索引作为可能的选项.
附加信息:我想将我的计划添加到优化器计划列表中(Optimiser已经为查询创建了许多计划).因此,在为查询选择最佳计划时,我希望优化人员也考虑我的计划.如果这种方式可行,那么优化器不需要每次都考虑强制索引.它可以将力指数作为计划生成的可能选项
据我所知,我试图明确提出这个问题.如果有人无法理解您的查询评论.
唯一的方法是FORCE INDEX从您的查询中删除.
您可以覆盖优化程序的计划,否则您可以让优化程序选择计划.
优化器无法判断使用索引是否会很慢.它试图在选择一个快速的计划时做出最好的猜测.
优化器可以更准确的唯一方法是运行两个查询,并比较性能差异,然后运行快速查询.这显然不实用,因此优化器旨在根据某些统计模型估算查询的成本.大多数情况下,这是准确的,优化器的选择是最好的.
您处理的一般概念是"内部数据库统计"(不是官方术语).也就是说,数据库引擎用于制定查询计划的信息.统计信息存储详细信息,如索引中的密钥分配,表行大小,计数,空行百分比,数据的清晰度等.
出于历史(和相关)性能原因,内部数据库统计信息不会即时更新,但通常会在DBA的要求下定期更新.在Postgres土地上,这些信息可以通过pg_statistic表格简洁地获得.不幸的是,MySQL并没有提供这些信息,但你可以从INFORMATION_SCHEMA和SHOW INDEXES中看到你可以收集的信息.
对于您的问题 - 查询计划提示的短暂有用性 - 是DB的统计数据不代表表数据.一般的响应是:更新DB的相关表的统计信息,您不需要在查询中提供优化器提示:
ANALYZE TABLE <table_name>;
Run Code Online (Sandbox Code Playgroud)
有一些需要注意的注意事项:
如果没有额外的措施,数据库引擎的这种分析是短暂的:它不会在数据库重启/重启时持续存在.选项是在数据库启动时重新分析表,或查看统计信息持久性.
这通过对数据进行采样来生成统计信息 - 查看随机表行的子集.从本质上讲,随机抽样意味着所收集的统计数据在任何特定运行中都可能不是实际数据的良好表示,从而导致查询计划不佳.您可以通过增加样本页面的数量innodb_stats_persistent_sample_pages
ANALYZE不是OPTIMIZE,你的表也可能需要优化. OPTIMIZE是一种昂贵的操作,需要锁定桌面,但在某些条件下可能非常有益.
ANALYZE是特定于表的,并不能弥补糟糕的表格布局.例如,我最近的任务是加速一组缓慢运行的报告查询.罪魁祸首?模式将时间和日期列存储为字符串,而不是本机数据类型.这具有重大意义,因为查询首先必须在比较之前将字符串转换为日期(包括数据中的错误),从而导致多个整个表扫描.很坏.
ANALYZE无法弥补糟糕的疑问.例如,与前一个项目符号点一样,类似WHERE SOME_FUNCTION( col ) > some_value意味着查询计划程序可能无法利用索引,因为每行必须首先执行FUNCTION以获取条件结果.并非总是如此,但经常在天真的SQL查询中找到.
ANALYZE无法弥补不良的正常化.不能承受潜在的大算法常数,通过适当的规范化,您将获得更大的大O算法胜利.
ANALYZE并没有创建索引.如果查询访问具有高基数但没有索引的列,则太糟糕了.知道根据已知或预期的查询将索引放入哪些列取决于DBA.
像往常一样,在这些情况下,将所有StackOverflow建议与盐一起使用:您负责数据或程序,并在您面前拥有实际运行的产品.你可以测试,你可以测量,你可以四处寻找.我们做不到.
FORCE INDEX今天可能会好,但明天会很糟糕.这是因为数据分布发生变化和/或查询中的常量发生变化.
有一些模式经常会导致选择"错误"的指数:
SELECT ...
WHERE ...
ORDER BY ...
Run Code Online (Sandbox Code Playgroud)
目前还不清楚是否优化WHERE或为ORDER BY.
SELECT ...
FROM a
JOIN b ON ...
WHERE a.x ...
AND b.y ...
Run Code Online (Sandbox Code Playgroud)
并且无论是过滤a.x还是b.y先过滤都不明显.(它不能同时对两者进行过滤.)
如果您提供特定查询,我们可能会提供特定提示.
有时,可以重新构造查询以欺骗优化器采用一条路径而不是另一条路径.版本8.0有许多"提示",但不一定比这更好FORCE INDEX. STRAIGHT_JOIN是另一种暗示的味道.
重新构造查询可能涉及将其中的一部分转换为子查询.但同样,你冒着"今天好,明天坏"的风险.
如果您有"过度标准化"(例如规范化日期时间,然后使用BETWEEN),则解决方案可能涉及非规范化.
你在使用'复合'索引吗?"范围" WHERE是指数中最后一个的一部分吗?(还有很多其他问题 - 让我们看一下具体的问题.)
小智 5
我所知道的,
Mysql不足以支持您的需求,因为缺少某种统计和机制,例如直方图,动态采样等.
因此,如果数据发生变化,虽然及时收集统计信息,缺少前面描述的必要内容,但优化器可能不会按预期行为.
你的两个问题可能是很好的做法,但最终用户很难.
或者您可以为oracle或maria db团队提供建议吗?
问:无论如何建议查询优化器在其计划生成期间使用强制索引作为可能的选项.如果使用强制索引是一个缓慢的计划,那么它可以使用正常的查询计划.
答:不会.优化器会根据其给定的内容执行它所做的事情.优化器不会忽略提示.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文本进行一些简单的调整来解决查询性能问题.有时更广泛的重新设计和重写.
有合适的索引(例如,考虑具有适当前导列的复合索引,并删除singleton列上的冗余索引)
确保统计数据是最新的并且代表表格(请注意,InnoDB使用一小部分页面收集统计数据.如果获取的页面不能代表表格,我们可以得到偏差的统计数据.
| 归档时间: |
|
| 查看次数: |
298 次 |
| 最近记录: |