-
-
Save arnaud-lb/2704404 to your computer and use it in GitHub Desktop.
| <?php | |
| use UseIndexWalker; | |
| use Doctrine\ORM\Query | |
| $query = $em->createQuery("SELECT f FROM Foo f WHERE f.a = 1 and f.b = 2"); | |
| $query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, 'UseIndexWalker'); | |
| $query->setHint(UseIndexWalker::HINT_USE_INDEX, 'some_index_name'); | |
| $query->getResult(); |
| <?php | |
| use Doctrine\ORM\Query\SqlWalker; | |
| /** | |
| * Quick hack to allow adding a USE INDEX on the query | |
| */ | |
| class UseIndexWalker extends SqlWalker | |
| { | |
| const HINT_USE_INDEX = 'UseIndexWalker.UseIndex'; | |
| public function walkFromClause($fromClause) | |
| { | |
| $result = parent::walkFromClause($fromClause); | |
| if ($index = $this->getQuery()->getHint(self::HINT_USE_INDEX)) { | |
| $result = preg_replace('#(\bFROM\s*\w+\s*\w+)#', '\1 USE INDEX (' . $index . ')', $result); | |
| } | |
| return $result; | |
| } | |
| } |
Here is mine that can use different indexes per DQL table aliases. Works with both createQuery and createQueryBuilder. Still a hack tho. Thx for the idea arnaud-lb!
https://github.com/ggergo/SqlIndexHintBundle
https://packagist.org/packages/ggergo/sqlindexhintbundle
@ggergo Thank you for sharing your version.
The only issue I encountered is that once the query hint is added we're forced to have all the DQL aliases listed. For example, sometimes you might only want to add a hint in a JOIN clause.
Once I updated the "walkFromClause" method to the following, it worked as expected:
public function walkFromClause($fromClause): string
{
$sql = parent::walkFromClause($fromClause);
$hints = $this->getQuery()->getHint(self::HINT_INDEX);
foreach ($this->getIndexHintParameters($fromClause) as $params) {
if (!array_key_exists($params['dqlAlias'], $hints)) {
continue;
}
$sql = $this->insertIndex($params['sqlKey'], $params['sqlTableAlias'], $hints[$params['dqlAlias']], $sql);
}
return $sql;
}
The difference here is the "array_key_exists()" check, which will only insert an index hint if listed.
Best,
Renato.
@renatogcarvalho Thank you for noticing! I added your fix. 👍 Best regards, Gergő
Another composer package: shipmonk/doctrine-mysql-index-hints
- works even for tables nor present in DQL, but present in SQL (Single Table Inheritance)
- supports Doctrine ORM 3
- supports subselects
Thanks for the solution ! 🙏
Small fix : in example.php line 8, you can use UseIndexWalker::class instead of 'UseIndexWalker'. It avoids having hardcoded strings in code + it manages if the file is in a different namespace. :)
thanks, you saved me.
Here is modified version of walker,
contains FIX for join-queries
http://stackoverflow.com/questions/16729011/index-hinting-in-doctrine2