让Doctrine使用MySQL中的"FORCE INDEX"

6

我在Doctrine的DQL中有一个查询需要能够使用MySQL的"FORCE INDEX"功能,以大幅减少查询时间。以下是该查询在普通SQL中的基本样子:

SELECT id FROM items FORCE INDEX (best_selling_idx)
WHERE price = ... (etc)
LIMIT 200;

我认为我需要扩展一些Doctrine组件才能使用DQL实现这个功能(或者有没有一种方法将任意SQL注入到Doctrin的查询中?)。 有人有什么想法吗?


我在Doctrine 2中遇到了同样的问题。与其编写自定义DQL函数重写为本地查询...,我将强制MySQL使用错误索引的andWhere()更改为andHaving()。只是想分享这个快速而简单的解决方法,以防其他使用Doctrine 2的人遇到此帖子。 - Adam V.
3个回答

7
我在网上找到了很少有用的Doctrine_RawSql示例,所以这里是我最终为创建查询所做的事情。
$q = new Doctrine_RawSql();
$q->select('{b.id}, {b.description}, {c.description}')
  ->from('table1 b FORCE INDEX(best_selling_idx) INNER JOIN table2 c ON b.c_id = c.id')
  ->addComponent('b', 'Table1 b')
  ->addComponent('c', 'b.Table2 c');

5
如果您不喜欢原生的SQL,可以使用以下修补程序。https://gist.github.com/arnaud-lb/2704404 此修补程序建议只创建一个自定义Walker,并按照以下方式对其进行设置。
$query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, 'UseIndexWalker');
$query->setHint(UseIndexWalker::HINT_USE_INDEX, 'some_index_name');

2

我创建了一个Doctrine SqlWalker扩展,用于在MySql上使用DQL应用USE INDEX和FORCE INDEX提示。该扩展可以与createQuery和createQueryBuilder一起使用,您可以针对每个DQL表别名设置不同的索引提示。

use Ggergo\SqlIndexHintBundle\SqlIndexWalker;
...
$query = ...;
$query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, SqlIndexWalker::class);
$query->setHint(SqlIndexWalker::HINT_INDEX, [
    'your_dql_table_alias'           => 'FORCE INDEX FOR JOIN (your_composite_index) FORCE INDEX FOR ORDER BY (PRIMARY)',
    'your_another_dql_table_alias'   => 'FORCE INDEX (PRIMARY)',
    ...
]);

https://github.com/ggergo/SqlIndexHintBundle


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接