【问题标题】:Symfony2 Doctrine+Twig query taking too longSymfony2 Doctrine+Twig 查询耗时太长
【发布时间】:2016-07-14 13:55:25
【问题描述】:

我目前正在构建一个查询以返回所需日期之间的一组记录,如下所示:

public function findBetweenDates(\Datetime $date1,\Datetime $date2)
{
        $date1=$date1->setTime(07,00,00);
        date_modify($date2,'+1 day');
        $date2->setTime(06,59,00);
        $qb = $this->getEntityManager()->createQueryBuilder()
            ->select('e')
            ->from("AppBundle:Movimento","e")
            ->andWhere('e.pesagem1 BETWEEN :from AND :to')
            ->setParameter('from', $date1 )
            ->setParameter('to', $date2)
            ->orderBy('e.id','DESC')

        ;
        $result = $qb->getQuery()->getResult();
        return $result;
    }

Movimento 类有一些 ManyToOne 连接,如下所示:

class Movimento
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

  /**
  * @ORM\ManyToOne(targetEntity="Service")
  * @ORM\JoinColumn(name="service", referencedColumnName="id")
  **/
   private $service;

当我得到记录并在树枝中呈现它们时:

 {% for item in items %}
    <tr>
         <td>{{ item.id }} </td>
        <td>{{ item.service.name }}</td>
//#MORE CODE BELOW //

通过从另一个实体调用 servico.name,我得到了大量不需要的查询,结果显示服务的名称而不是它的 id。 我们在每个响应中都在谈论 6k 范围内的记录。

如果可以使用我的查询构建器优化此查询,或者我应该将整个查询重新制作成一个“SQL”示例,我需要一些帮助:

Select a.name, b.id
From service as a, movimento as b
Between bla bla bla

非常感谢任何帮助/建议。

编辑 1 阅读这篇文章后,我更改了我的查询生成器Symfony 2/Doctrine: How to lower the num of queries without losing the benefit of ORM?

我确实将 175 个查询减少到一个

$qb = $this->createQueryBuilder('e')
            ->addSelect('service')->join('e.service','service')
            ->addSelect('motorista')->join('e.motorista','motorista')
            ->addSelect('residuo')->join('e.residuo','residuo')
          //  ->from("AppBundle:Movimento","e")
            ->andWhere('e.pesagem1 BETWEEN :from AND :to')
            ->setParameter('from', $date1 )
            ->setParameter('to', $date2)
            ->orderBy('e.id','DESC')

但是页面仍然需要大约 8 秒来加载(它的 6900 条记录),在检查性能后,我的新查询的响应时间是 177.79 毫秒,但我的 twig+ 控制器需要剩余的 7.x 秒,因为它显示图片 我的控制器非常简单

 public function getMovimentosAction(Request $request)
    {

        $startDate = $request->request->get('startDate');
        $endDate = $request->request->get('endDate');

        if (empty($startDate))
            $startDate = date("Y-m-d") ;
        if (empty($endDate))
            $endDate = date("Y-m-d");

        $em=$this->getDoctrine()->getRepository('AppBundle:Movimento');
        $dados=$em->findBetweenDates(new \DateTime($startDate),new \DateTime($endDate));

        return $this->render('AppBundle:Movimentos:logtable-movimento.html.twig', array(
            'items' => $dados
        ));
    }

我的树枝只是遍历行并将它们显示在表格上,就像我在上面给出的部分示例一样。

任何帮助/建议将不胜感激。

EDIT2 我通过 ajax 传递的视图被呈现为 datatable.js

<table id="example" class="table table-striped table-bordered table-hover" cellspacing="0" width="100%">
    <thead class="dataTableHeader">
    <tr>
        <th>Talão</th>
        <th>Nº Talão</th>
        <th>Motorista</th>
        <th>Residuo</th>
        <th>Serviço</th>
        <th>Matricula</th>
        <th>1º Pesagem</th>
        <th>Peso Liquido</th>
        <th>Fluxo</th>
        <th>Circuito</th>
        <th>Verificado</th>
        <th></th>
    </tr>
    </thead>
    <tfoot class="dataTableHeader">
    <tr>
        <th>Talão</th>
        <th>Nº Talão</th>
        <th>Motorista</th>
        <th>Residuo</th>
        <th>Serviço</th>
        <th>Matricula</th>
        <th>1º Pesagem</th>
        <th>Liquido</th>
        <th>Fluxo</th>
        <th>Circuito</th>
        <th>Verificado</th>
        <th></th>
    </tr>
    </tfoot>
    <tbody>
    {% for item in items %}
    <tr>
        <td align="center"><a href="{{ path("_movimento_generate_pdf",{ id: item.id }) }}"> <i class="fa fa-print fa-2x" aria-hidden="true"></i>
            </a></td>
        <td>{{ item.id }} <a><i class="fa fa-eye" title="Visualizar Movimento" aria-hidden="true"></i></a>
        </td>
        <td>{{ item.motorista.idFuncionario }} - {{ item.motorista.nome }}</td>
        <td>{{ item.residuo.nome }}</td>
        <td>{{ item.servico.nome }}</td>
        <td>{{ item.matricula }}</td>
        <td>{{ item.pesagem1|date('Y-m-d h:m') }}</td>
        <td>{{ item.liquido }} kg</td>
        <td>{% if item.tipoMovimento == 1 %} Entrada {% else %} Saida {% endif %}</td>
        <td>{{ item.circuito.code | default(" ") }}</td>
        <td class="text-center">{% if item.enable==1 %}
                <span style="color: transparent">&nbsp;</span>
                <i class="fa fa-circle" aria-hidden="true" style="color: green"></i>
            {% else %}

                <i class="fa fa-times" aria-hidden="true" style="color: red;"></i>
            {% endif %}
        </td>
        <td class="text-center">
            <a class="btn btn-default" href="{{ path('_movimentos_edit',{ 'id' : item.id}) }}">
                <i class="fa fa-cog" title="Editar" aria-hidden="true"></i>
                <span class="sr-only">Settings</span>
            </a>
        </td>
    </tr>

    {% endfor %}


    </tbody>
</table>

在我的html中

 $("#submitButtonQuery").click(function(event){
            event.preventDefault();
            var l = Ladda.create(this);
            l.toggle();
            $.post( "/movimentos/getList",
                $( "#formAjaxify" ).serialize())
                .done(function(data)
                {
                    $('#example').remove();

                    $("#tabelaLog").html(data);
                    oTable=$('#example').DataTable(
                        {
                            "scrollX": true,
                            responsive: true,

                            "language": {
                                "url": "http://cdn.datatables.net/plug-ins/1.10.11/i18n/Portuguese.json"
                            }
                        }
                    );
                    oTable.order( [ 0, 'desc' ] )
                        .draw();
      })
        .always(function(){
            l.toggle()})
    ;
});

【问题讨论】:

  • 你能发布你的完整树枝模板吗?
  • 您真的需要一次呈现所有条记录吗?你不能对结果进行分页吗?
  • 嗯,一次导入所有记录的好处是,它可以更轻松地使用数据表进行搜索以及导出到 pdf/csv 功能。

标签: symfony orm doctrine-orm twig query-builder


【解决方案1】:

只要您在“Movimento”和“Service”之间建立了连接,那么对于您获得的每个“movimento”,一个“服务”将被一起序列化。这意味着,如果您有一个返回 100 'movimento' 的查询,那么连同它一起将需要获取所有 'service' 对象 (100)。

如果您不想将服务作为每个项目中的对象(AKA item.service.blahblah),那么您需要进行更直接的查询。

如果您使用查询生成器执行此操作,那么您将需要以下内容:

$repository = $this->getDoctrine()
        ->getRepository('YourownBundle:Movimento'); //the main repo from which to get data

    $query = $repository->createQueryBuilder('m') // query builder on repo
        ->join('m.service', 's') // join the second object to select from
        ->select('m.id') // select everything from m objet
        ->addSelect('s.name') // select everything from service (s) object
        ->where('e.pesagem1 BETWEEN :from AND :to')
        ->setParameter('from', $date1 )
        ->setParameter('to', $date2)
        ->orderBy('e.id','DESC')

您的其余代码应该与您拥有的一样...但是您没有序列化对象,而只有您所做的选择(例如 m.id、s.name)

【讨论】:

    猜你喜欢
    • 2015-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-28
    • 2011-02-07
    • 2013-04-08
    • 1970-01-01
    相关资源
    最近更新 更多