简体   繁体   English

Symfony2:使用flush()或persist()优化数据处理

[英]Symfony2: use flush() or persist() to optimize data handling

Im working with Symfony (const version="2.5.10") and using XAMPP with PHP version of 5.5.19 我正在使用Symfony(常量版本=“ 2.5.10”)并在PHP版本5.5.19中使用XAMPP

My problem is I keep on getting out of memory error. 我的问题是我不断出现内存不足错误。 Because I think I query thousand of data (rows) in the database. 因为我想查询数据库中的数千个数据(行)。 For info, I have a lot of data in the database. 有关信息,我在数据库中有很多数据。 I want to use flush() or anything that could be use to optimize my data handling. 我想使用flush()或任何可以用来优化数据处理的东西。

Here is my code in my indexAction controller: 这是我的indexAction控制器中的代码:

public function indexAction(){
  $em = $this->getDoctrine()->getManager();
  $po = $em->getRepository('MatrixEdiBundle:EdiTransactionDetail')->findDocs('850');
  return $this->render('MatrixEdiBundle:Matrix:index.html.twig', array('po' => $po));
}

index.html.twig index.html.twig

{% extends '::layout.html.twig' %}
{# {% include 'MatrixEdiBundle:Matrix:header.html.twig'%} #}
{% block body %}
<div class="content">
</br>
  <table id="datTable"  class="table table-bordered table-condensed table-hover">
      <thead>
        <th colspan="8">Edi Matrix</th>
        <tr>
          <th>Po Numbers</th>
          <th>Trading Partner Id</th>
          <th>PO 855 Acknowledgement</th>
          <th>PO 997 Acknowledgement</th>
          <th>Advance Shipment Notice</th>
          <th>Invoice</th>
          <th>Purchase Order Change</th>
          <th>Order Status</th>
        </tr>
      </thead>
      <tbody>
      {% for tran in po %}
        <tr>
            <td><a href="{{ path('matrix_edi_showpo', {'po_num':  tran.poNumber}) }}"data-toggle="modal" data-target="#myModal">{{tran.poNumber}}</td>

            <td>{{tran.ediTransaction.senderId}}</td>

            <td><a href="{{ path('matrix_edi_findAll', {'po_num':  tran.poNumber, 'sender_id':  tran.ediTransaction.senderId, 'doc_type': 855}) }}"data-toggle="modal"data-target="#myModal">
            {{ render(controller('MatrixEdiBundle:Matrix:matrix', {
            'po_num': tran.poNumber, 'sender_id': tran.ediTransaction.senderId, 'reciever_id': tran.    ediTransaction.receiverId, 'doc_type': 855, 'gs_number': tran.ediTransaction.gsNumber })) }}</a>
            </td>

            <td><a href="{{ path('matrix_edi_poack', {'gs_number':  tran.ediTransaction.gsNumber, 'receiver_id':  tran.ediTransaction.receiverId, 'sender_id': tran.ediTransaction.senderId}) }}"data-toggle="modal"data-target="#myModal">
            {{ render(controller('MatrixEdiBundle:Matrix:matrix', {
            'po_num': tran.poNumber, 'sender_id': tran.ediTransaction.senderId, 'reciever_id': tran.    ediTransaction.receiverId, 'doc_type': 997, 'gs_number': tran.ediTransaction.gsNumber })) }}</a>
            </td>

            <td><a href="{{ path('matrix_edi_findAll', {'po_num':  tran.poNumber, 'sender_id':  tran.ediTransaction.senderId, 'doc_type': 856}) }}"data-toggle="modal"data-target="#myModal">{{ render(controller('MatrixEdiBundle:Matrix:matrix', {
            'po_num': tran.poNumber, 'sender_id': tran.ediTransaction.senderId, 'reciever_id': tran.ediTransaction.receiverId, 'doc_type': 856, 'gs_number': tran.ediTransaction.gsNumber }))}}</a>
            </td>

            <td><a href="{{ path('matrix_edi_findAll', {'po_num':  tran.poNumber, 'sender_id':  tran.ediTransaction.senderId, 'doc_type': 810}) }}"data-toggle="modal"data-target="#myModal">{{ render(controller('MatrixEdiBundle:Matrix:matrix', {'po_num': tran.poNumber, 'sender_id': tran.ediTransaction.senderId, 'reciever_id': tran.ediTransaction.receiverId, 'doc_type': 810, 'gs_number': tran.ediTransaction.gsNumber})) }}</a>
            </td>

            <td><a href="{{ path('matrix_edi_findAll', {'po_num':  tran.poNumber, 'sender_id':  tran.ediTransaction.senderId, 'doc_type': 860}) }}"data-toggle="modal"data-target="#myModal">{{ render(controller('MatrixEdiBundle:Matrix:matrix', {'po_num': tran.poNumber, 'sender_id': tran.ediTransaction.senderId, 'reciever_id': tran.ediTransaction.receiverId, 'doc_type':860, 'gs_number': tran.ediTransaction.gsNumber})) }}</a>
            </td>

          <td><a href="{{ path('matrix_edi_findAll', {'po_num':  tran.poNumber, 'sender_id':  tran.ediTransaction.senderId, 'doc_type': 870}) }}"data-toggle="modal"data-target="#myModal">{{ render(controller('MatrixEdiBundle:Matrix:matrix', {
        'po_num': tran.poNumber, 'sender_id': tran.ediTransaction.senderId, 'reciever_id': tran.ediTransaction.receiverId, 'doc_type': 870, 'gs_number': tran.ediTransaction.gsNumber
    })) }}</a></td>

        </tr>
      {% endfor %}
    </tbody>
    </table>
  </div> 


<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="false" >
    <div class="modal-dialog">
        <div class="modal-content" style="width: 650px;">
            <div class="modal-header" style="background-color: #2d6ca2; color: white;">
                <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true" style="color: white;">×</span><span class="sr-only">Close</span></button>
                <h4 class="modal-title" id="myModalLabel" >Details</h4>
            </div>
      <div class="modal-body">
          Loading, please wait......
          <div class="bootstrap-table">

              <div class="fixed-table-container" style="height: 299px; padding-bottom: 37px;">
                <div class="fixed-table-body">
                  <div class="fixed-table-loading" style="top: 27px; display: none;">Loading, please wait…</div>
                </div>
                <div class="fixed-table-pagination"></div>
              </div>
          </div><div class="clearfix"></div>
      </div>  

      <div class="modal-footer">
          <button type="button" class="btn btn-primary" data-dismiss="modal" >Close</button>
      </div>
    </div><!-- /.modal-content -->
  </div><!-- /.modal-dialog -->
</div><!-- /.modal -->
{% endblock %}

{% block javascripts %}
{% javascripts
  'bundles/matrixdoc/js/jQuery.js'
  'bundles/matrixdoc/js/jquery.dataTables.min.js'
  'bundles/matrixdoc/js/dataTables.bootstrap.js'
  'bundles/matrixdoc/js/bootstrap.js'
   %}
  <script src="{{ asset_url }}"></script>
  <script type="text/javascript">
  $(document).ready(function() {
    $('#datTable').dataTable( {
      "scrollY": "400px",
      "scrollCollapse": true,
      "pagingType": "simple",
    });
    $('body').on('hidden.bs.modal', '.modal', function () {
      $(this).removeData('bs.modal');
    });
    $(document).on("hidden.bs.modal", function (e) {
      $(e.target).removeData("bs.modal").find(".modal-content").empty();
    });
    });
</script>
{% endjavascripts %}
{% endblock %}

You should use pagination getting your data with limits and coupled with partial to get your needed fields if you don't need everything. 如果不需要所有内容,则应使用分页来获取有限的数据,并结合使用partial获得所需的字段。

http://zrashwani.com/pagination-optimization-symfony2-doctrine/#.VV1av_mSwbg http://zrashwani.com/pagination-optimization-symfony2-doctrine/#.VV1av_mSwbg

for partial in DQL , simple example for user: 对于DQL中的部分用户,针对用户的简单示例:

//partial_fields is an array, which can be passed like this $repo->getPartialUser($user_id, array('field1', 'field2', 'etc..');
    public function getPartialUser($id, $partial_fields){
        $qb = $this->_em->createQueryBuilder()
            ->select('partial u.{'.implode(',',$partial_fields).'}')
            ->from('AcmeUserBundle:User', 'u')
            ->where('u.id = :id')
            ->setParameter('id', $id);
        $result = $qb->getQuery()->getOneOrNullResult();
        return $result;
    }

EDIT EXAMPLE CODE : 编辑示例代码:

i will give you an example but you will probably still need to adapt it to your code or maybe it will work out of the box. 我会举一个例子,但您可能仍需要将其调整为适合您的代码,否则它可能会立即可用。

First you need a new twig with simple piece of code to show pages numbers for navigation below the table (note that i will not use datatables paginator but we will keep it for table layout rendering) : 首先,您需要一个带有简单代码段的新树枝,以在表下方显示用于导航的页码(请注意,我将不使用datatables分页器,但我们将其保留用于表布局渲染):

pager.html.twig pager.html.twig

<div class="pagination">
    <div class="pagination-buttons">
        {% if pagination.page>1 %}
            <a href="{{ path(pagination.route,
            pagination.route_params|merge({'page': 1})) }}"><<</a>
            <a href="{{ path(pagination.route,
            pagination.route_params|merge({'page': pagination.page-1})) }}"><</a>
        {% endif %}
        {#display p numbers only from p-4 to p+4 but don't go <1 or >pages_count#}
        {% for p in range(max(pagination.page-4, 1),
        min(pagination.page+4, pagination.pages_count)) %}
            <a{% if p == pagination.page %} class="current-page"{% endif %}
                    href="{{ path(pagination.route,
                    pagination.route_params|merge({'page': p})) }}">{{ p }}</a>
        {% endfor %}
        {% if pagination.page<pagination.pages_count %}
            <a href="{{ path(pagination.route,
            pagination.route_params|merge({'page': pagination.page+1})) }}">></a>
            <a href="{{ path(pagination.route,
            pagination.route_params|merge({'page': pagination.pages_count})) }}">>></a>
        {% endif %}
    </div>
</div>

EdiTransactionDetailRepository: EdiTransactionDetailRepository:

add a function with your field that you use in your table : 在表中使用的字段中添加一个函数:

public function  getPagedDocs($page = 1, $limit = 50)
    {
        $qb = $this->_em->createQueryBuilder()
             ->select('partial d.{field1,field2 , etc..},
                       partial et.{field1,field2, etc..}'
              ))//select doc fields and second partial for your join select edittransaction fields if you have other joins add another partial etc.. 
             ->from('YourBundle:DocsEntity', 'd')
             ->innerJoin('d.ediTransaction', 'et')//not sure which join you need i have no clue but i believe you will want an inner one since you will want a doc to have a ediTransaction because i didn't see any checks in your twig for it if null.
             ->setFirstResult(($page - 1) * $limit)
             ->setMaxResults($limit);

        $paginator =  new Paginator($qb, $fetchJoinCollection = false);//for more performance fetchjoincollection to false if you have joined tables
        $paginator->setUseOutputWalkers(false);//for more performance set to false for more information http://www.doctrine-project.org/jira/browse/DDC-2890

        return $paginator;
    }

PS: Change limit to how many records you want to show in each page depending on the load of data you have make it lower if it is slow for 50 this is depend on how much data each row have. PS:更改限制为要在每个页面中显示多少条记录,具体取决于您拥有的数据负载,如果速度变慢50条,则将其降低,这取决于每行有多少数据。

Next the indexAction in your controller : 接下来是控制器中的indexAction:

public function indexAction($page){
  $em = $this->getDoctrine()->getManager();
  $po = $em->getRepository('MatrixEdiBundle:EdiTransactionDetail')->getPagedDocs($page, 50);
  $count = $po->count();
  $pagination = array(
        'page' => $page,
        'route' => 'docs_index_route_name', //i dont know which name you have but it should be the route name of this indexAction
        'route_params' => array()
    );
    if ($max_records > 0)
        $pagination['pages_count'] = max(ceil($count / $max_records), 1);
  return $this->render('MatrixEdiBundle:Matrix:index.html.twig', array('po' => $po,
  'pagination' => $pagination
    ));
}

Routing: 路由:

You need to modify the route of your indexAction as we added a parameter page you need to add it for the route too : 您需要修改indexAction的路由,因为我们添加了一个参数页面,您也需要为其添加路由:

index_docs:
    pattern:  /index/{page}
    defaults: { _controller: "YourBundle:Controller:index", page: 1 }

NOTE : you will need to change the names and stuff i dont know you controller names and bundles so normally you will only need to add /{page} to the pattern and , page:1 to your _controller config which is the default value. 注意:您将需要更改名称和我不知道的控制器名称和捆绑包,因此通常您只需要在模式中添加/ {page},并将_page:1添加到_controller配置中,这是默认值。

Last thing to do is your index.html.twig which need to include our pager.html.twig 最后要做的是您的index.html.twig,其中需要包含我们的pager.html.twig

include this piece of code after you close your table : 关闭表后,请包含以下代码:

    {% if po|length > 0  and pagination['pages_count'] is defined and pagination['pages_count'] > 0 %}
        {#---------Pager----------#}
        <div style="text-align:center;">
            {% include 'YourBundle:EntityDoc:pager.html.twig' %}
        </div>
    {% endif %}

NOTE : The include is the path to the file where you create the pager.html.twig i assume you are familiar with how this works. 注意:include是您在其中创建pager.html.twig的文件的路径,前提是您熟悉它的工作原理。

So if i didn't forget anything this should work out of the box , it should enhance greatly your performance but i am afraid that your render controller there for each row may still be problematic. 因此,如果我没有忘记任何应立即使用的功能,它将大大提高您的性能,但是我担心在那里的每一行的渲染控制器仍然可能会出现问题。 But try this solution first and see, it depends what you put inside those controllers. 但是,请首先尝试此解决方案,然后看看它是否取决于您在这些控制器中放置的内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM