shipmonk / doctrine-mysql-optimizer-hints
为 Doctrine 提供的定制 SQL 查询器,允许在不使用原生查询的情况下使用 MySQL 优化器提示
Requires
- php: ^8.1
- shipmonk/doctrine-hint-driven-sql-walker: ^2.0.0
Requires (Dev)
- doctrine/collections: ^2.1
- doctrine/dbal: ^3.7
- doctrine/event-manager: ^2.0
- doctrine/orm: ^3.0
- editorconfig-checker/editorconfig-checker: ^10.5.0
- ergebnis/composer-normalize: ^2.42.0
- phpstan/phpstan: ^1.11.1
- phpstan/phpstan-phpunit: ^1.4.0
- phpstan/phpstan-strict-rules: ^1.6.0
- phpunit/phpunit: ^10.5.13
- shipmonk/composer-dependency-analyser: ^1.3.1
- shipmonk/phpstan-rules: ^3.0.0
- slevomat/coding-standard: ^8.15.0
This package is auto-updated.
Last update: 2024-09-02 11:22:44 UTC
README
此库提供了一种简单的方法,通过 MySQL 的优化器提示 将 SELECT 查询集成到使用 Doctrine 查询语言 编写的查询中,通过 自定义 SqlWalker。不再需要原生查询。
安装
composer require shipmonk/doctrine-mysql-optimizer-hints
示例用法
$result = $em->createQueryBuilder() ->select('u.id') ->from(User::class, 'u') ->andWhere('u.id = 1') ->getQuery() ->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, HintDrivenSqlWalker::class) ->setHint(OptimizerHintsHintHandler::class, ['SET_VAR(sql_mode=ONLY_FULL_GROUP_BY)']) ->getResult();
这将产生以下 SQL
SELECT /*+ SET_VAR(sql_mode=ONLY_FULL_GROUP_BY) */ u0_.id AS id_0 FROM user u0_ WHERE u0_.id = 1
请注意您放置的优化器提示,您基本上是在那里编写 SQL,但 MySQL 只在发生错误时产生警告。
用例
限制/扩展单个查询的最大执行时间
任何合理的应用程序都会使用一些全局的 max_execution_time 来避免查询运行数小时。但您可能希望为单个长时间运行的查询打破这一限制。通过 SET max_execution_time = 10000;
来做这样的事情是棘手的,因为您应该在查询结束后立即将其恢复到之前的值。这会导致围绕它的代码变得复杂,优化器提示免费为您做这件事
->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, HintDrivenSqlWalker::class) ->setHint(OptimizerHintsHintHandler::class, ['MAX_EXECUTION_TIME(1000)'])
查询优化
有时,通过 强制使用某些索引 并不足以帮助 MySQL 优化器调整执行计划中表的顺序。连接顺序优化器提示 是通往这一目标的途径。最简单的用法是使用 JOIN_FIXED_ORDER()
强制表的顺序与您所写完全一致。
->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, HintDrivenSqlWalker::class) ->setHint(OptimizerHintsHintHandler::class, ['JOIN_FIXED_ORDER()'])
测试不可见索引
当处理生产环境中的复杂查询优化时,您只能猜测您想出的新索引是否有帮助。从 MySQL 8.0 开始,您可以创建 不可见索引(这些由引擎维护但不使用)。但您可以为要测试的查询启用不可见索引
->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, HintDrivenSqlWalker::class) ->setHint(OptimizerHintsHintHandler::class, ["SET_VAR(optimizer_switch = 'use_invisible_indexes=on')"])
扩大单个查询的 group_concat 限制
group_concat_max_len 的默认限制为 1024,但您可以将其设置得更大
->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, HintDrivenSqlWalker::class) ->setHint(OptimizerHintsHintHandler::class, ["SET_VAR(group_concat_max_len = 4294967295)"])
与索引提示结合使用
自 2.0.0 版本起,您可以结合使用此库与 shipmonk/doctrine-mysql-index-hint
$result = $em->createQueryBuilder() ->select('u.id') ->from(User::class, 'u') ->andWhere('u.id = 1') ->getQuery() ->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, HintDrivenSqlWalker::class) ->setHint(OptimizerHintsHintHandler::class, ['MAX_EXECUTION_TIME(1000)']) ->setHint(UseIndexHintHandler::class, [IndexHint::force(User::IDX_FOO, User::TABLE_NAME)]) ->getResult();