2017-10-18 3 views
-1

J'utilise Codeigniter et actuellement face à un résultat de recherche extrêmement lent lorsque je tente d'interroger une liste de DB via mon moteur de recherche (système php). Je crois que le problème est très lié au codage de mes requêtes car le reste des pages qui montre le DB se charge rapidement mais pas lorsque je recherche des DB entre les dates. La page est comme charger plus de 10 minutes lorsque j'effectue la recherche. S'il vous plaît vérifier est-il quelque chose de mal avec mon codage ou peut tout expert s'il vous plaît me fournir une meilleure suggestion pour améliorer mon codage:Lente requête PHP de MYSQL lors de la recherche entre les dates

public function get_transaction_record($search,$per_pg,$offset){ 
     $fill = array((int)1); 
     $temp = array(); 
     $data = array(); 
     $sQuery = "SELECT t.*,p.product_name,d.deposit_id,w.withdrawal_id,m.username,m.lucky_id,m.contact_no,u.username as admin, 
        b.name as bankname,b.holder_name, d.promo as prm, m.fullname, d.turnover as tover 
        FROM tbl_transaction t 
        INNER JOIN tbl_product p ON t.product_id = p.product_id 
        INNER JOIN tbl_member m ON m.member_id = t.member_id 
        LEFT JOIN tbl_deposit d ON t.transaction_id = d.transaction_id 
        LEFT JOIN tbl_withdrawal w ON t.transaction_id = w.transaction_id 
        INNER JOIN tbl_banks b ON t.bank_id = b.bankID 
               LEFT JOIN tbl_promotion pro ON pro.promotion_id = d.promotion_id 
        LEFT JOIN tbl_user u ON u.user_id = t.admin_id WHERE 1 = ? AND t.status != 9"; 

     if(strlen($search['date_from']) > 0 && strlen($search['date_to']) > 0 ){ 
      $sQuery .= ' AND date(t.date_create) BETWEEN ? '; 
      array_push($fill,$search['date_from']); 

      $sQuery .= ' AND ? '; 
      array_push($fill,$search['date_to']); 
     }else{ 
      if(strlen($search['date_from']) > 0){ 
       $sQuery .= ' AND date(t.date_create) = ? '; 
       array_push($fill,$search['date_from']); 
      } 
      if(strlen($search['date_to']) > 0){ 
       $sQuery .= ' AND date(t.date_create) = ? '; 
       array_push($fill,$search['date_to']); 
      } 
     } 

     if(strlen($search['status']) > 0){ 
      $sQuery .= ' AND t.status = ? '; 
      array_push($fill,$search['status']); 
     } 
        if(strlen($search['contact_no']) > 0){ 
      $sQuery .= ' AND m.contact_no LIKE "%"?"%" '; 
      array_push($fill,$search['contact_no']); 
     } 

     if(strlen($search['fullname']) > 0){ 
      $sQuery .= ' AND m.fullname LIKE "%"?"%" '; 
      array_push($fill,$search['fullname']); 
     } 
     if(strlen($search['username']) > 0){ 
      $sQuery .= ' AND m.username LIKE "%"?"%" '; 
      array_push($fill,$search['username']); 
     } 

     if(strlen($search['lucky_id']) > 0){ 
      $sQuery .= ' AND m.lucky_id = ? '; 
      array_push($fill,$search['lucky_id']); 
     } 

     if(strlen($search['email']) > 0){ 
      $sQuery .= ' AND m.email LIKE "%"?"%" '; 
      array_push($fill,$search['email']); 
     } 

     if(strlen($search['user_id']) > 0){ 
      $sQuery .= ' AND t.admin_id = ? '; 
      array_push($fill,$search['user_id']); 
     } 

     if(strlen($search['product_id']) > 0){ 
      $sQuery .= ' AND t.product_id = ? '; 
      array_push($fill,$search['product_id']); 
     } 

     if(strlen($search['bankID']) > 0){ 
      $sQuery .= ' AND t.bank_id = ? '; 
      array_push($fill,$search['bankID']); 
     } 

     if(strlen($search['type']) > 0){ 
      $sQuery .= ' AND t.type = ? '; 
      array_push($fill,$search['type']); 
     } 

     if(strlen($search['bankid2']) > 0){ 
      $sQuery .= ' AND w.bankid2 = ? '; 
      array_push($fill,$search['bankid2']); 
     } 

    // $sQuery .= " ORDER BY t.date_create DESC LIMIT ?,? "; 
      $sQuery .= " ORDER BY t.date_create DESC LIMIT ?,? "; 
     // $sQuery .= " ORDER BY CASE t.status WHEN 0 THEN 0 WHEN 1 THEN 1 WHEN -1 THEN 9 END, t.date_create DESC LIMIT ?,? "; 
     array_push($fill,(int)$offset,(int)$per_pg); 

     $query = $this->db->query($sQuery, $fill); 
     //echo $this->db->last_query(); 
     if($query->num_rows() > 0){ 
      foreach ($query->result() as $rows): 
       $temp['bankname']  = $rows->bankname; 
       $temp['holder_name'] = $rows->holder_name; 
       $temp['ref']   = $rows->ref; 
       $temp['username']  = $rows->username; 
       $temp['fullname']  = $rows->fullname; 
       $temp['lucky_id']  = $rows->lucky_id; 
       $temp['admin']   = $rows->admin; 
       $temp['contact_no']  = $rows->contact_no; 
       $temp['product_name'] = $rows->product_name; 
            $temp['promo'] = $rows->promo; 
       $temp['transaction_id'] = $rows->transaction_id; 

       $temp['member_id']  = $rows->member_id; 
       $temp['type']   = $rows->type; 
       $temp['product_id']  = $rows->product_id; 
       $temp['deposit_id']  = $rows->deposit_id; 
       $temp['withdrawal_id'] = $rows->withdrawal_id; 
       $temp['amount']   = $rows->amount; 
            $temp['turnover']   = $rows->turnover; 
       $temp['status']   = $rows->status; 
       $temp['remark']   = $rows->remark; 
       $temp['day']   = $rows->day; 
       $temp['month']   = $rows->month; 
       $temp['year']   = $rows->year; 
       $temp['date_create'] = $rows->date_create; 
       $temp['date_update'] = $rows->date_update; 
       $temp['create_by']  = $rows->create_by; 
            $temp['prm']   = $rows->prm; 
            $temp['tover']   = $rows->tover; 
            if($rows->promotion_id > 0){ 
              $temp['promo'] = $this->get_promotion_details($rows->promotion_id); 
            }else{ 
              $temp['promo'] = NULL; 
            } 
       array_push($data, $temp); 
      endforeach; 
     } 
     return $data; 
    } 

code mis à jour comme ci-dessus

IMG FOR tbl_transaction SHOW CREATE TABLE

Merci. Tout d'abord, vous n'avez aucun index défini pour votre table de transactions.

+3

Lorsque vous demandez une aide à l'optimisation des requêtes, publiez toujours le message "SHOW CREATE TABLE" pour toutes les tables de votre requête et le champ "EXPLAIN" pour la requête. Et ne nous faites pas suivre votre code pour comprendre le SQL final. Montrez-nous le code SQL, pas le code qui construit la chaîne SQL. –

+0

@Randall une liste très longue que le système impliqué plus de 10k lignes d'entrée db quotidienne. Mais il se charge assez rapidement si je regarde la page sans chercher une certaine date. –

+0

'date()' ne peut pas utiliser un index – Strawberry

Répondre

1

Ainsi, toute recherche est obligée de faire un scan de table. Il est important d'utiliser des index pour accélérer les recherches. Vous pourriez aimer ma présentation How to Design Indexes, Really. Ou la vidéo: https://www.youtube.com/watch?v=ELR7-RdU9XU

Ceci est probablement l'indice le plus important pour vous de créer:

ALTER TABLE tbl_transaction ADD INDEX (create_date); 

Mais même après que vous avez un index, lorsque vous essayez de rechercher une expression comme celle-ci, il peut n'utilisez pas l'index.

date(t.date_create) BETWEEN ? AND ? 

Vous devez réécrire si la colonne indexée est seul:

t.date_create BETWEEN ? AND ? 

Mais cela signifie que vous voulez que le premier paramètre à « terrassé » en temps 00:00:00 et le second paramètre être "plafonné" au temps 23:59:59, pour s'assurer que le date_create avec n'importe quel composant de temps correspond à la plage de dates que vous voulez qu'il corresponde.

if(strlen($search['date_from']) > 0 && strlen($search['date_to']) > 0 ){ 
    $from = search['date_from'] . ' 00:00:00'; 
    $to = search['date_to'] . ' 23:59:59'; 

    $sQuery .= ' AND t.date_create BETWEEN ? AND ?'; 
    array_push($fill,$from); 
    array_push($fill,$to); 
} 

De même, même pour les recherches pour une date précise, il faut encore faire une gamme:

else if(strlen($search['date_from']) > 0){ 
    $from = search['date_from'] . ' 00:00:00'; 
    $to = search['date_from'] . ' 23:59:59'; 

    $sQuery .= ' AND t.date_create BETWEEN ? AND ?'; 
    array_push($fill,$from); 
    array_push($fill,$to); 
} 

Si vous lisez ma présentation sur la conception d'index, vous aurez remarqué qu'une condition de plage comme celui sur votre create_date signifie que les colonnes suivantes dans l'index n'aideront pas la recherche. Vous pouvez utiliser des index multi-colonnes, mais toutes les colonnes impliquées dans les conditions d'égalité doivent être à gauche dans l'index.

En outre, vous avez plusieurs conditions qui peuvent ou peuvent ne pas être présentes, selon les critères de recherche de l'utilisateur. Ceci est également difficile à optimiser, car une recherche indexée utilise uniquement les colonnes de l'index de gauche à droite. Si vous ignorez une colonne parce que la recherche n'en a pas besoin, les colonnes suivantes ne vous aideront pas.

Un autre type de condition dans votre recherche est la correspondance de modèle de texte avec LIKE '%'?'', au lieu de conditions d'égalité. Ces recherches LIKE ne peuvent pas utiliser un index conventionnel, mais elles peuvent utiliser un fulltext search index spécial. J'ai une présentation pour ça aussi: Full Text Search Throwdown. Vidéo: https://www.youtube.com/watch?v=V8yA8C3CZOc