recherche

Maison  >  Questions et réponses  >  le corps du texte

Les données renvoyées par la requête php sont trop volumineuses et l'importation de fichiers csv est très lente.

Le framework utilise ci et la base de données est sqlsrv (sql server 2008). L'ensemble de résultats renvoyé par la requête SQL contient 20 000 éléments de données. J'exécute cette instruction SQL dans le framework ci. La page Web continue de tourner. faire pivoter 20 000 éléments de données. Cela prend environ quelques secondes, mais mon instruction SQL est exécutée en quelques secondes dans SQL Server 2008 R2. Lorsque j'utilise la requête SQL intégrée dans CI, le temps d'exécution est de 200 millisecondes, ce qui signifie que mon instruction ne l'est pas. lent. Personnellement, je pense que c'est trop lent en raison d'un trop grand nombre de données renvoyées. Il renvoie 20 000 éléments de données et environ 20 champs. Parce que je fais des statistiques et que j'exporte les données dans un fichier CSV, il y a donc beaucoup de données. Je m'occupe de ça ?
Mon instruction SQL est select * from table which create_time between 'xxxx-xx-xx 00:00:00' et 'xxxx-xx-xx 23:59:59' ; time Si la plage est petite, les données seront moindres. Si la plage est grande, les données seront volumineuses. Lorsque les données sont volumineuses, ce sera très lent.

fonction publique aa(){

$sql ="select * from table where create_time between 'xxxx-xx-xx 00:00:00' and 'xxxx-xx-xx 23:59:59'";
$result=$this->db->query($sql)-result_array();

}

C'est déjà la requête la plus simple. L'instruction SQL peut être vérifiée en quelques secondes, mais elle est très lente à exécuter avec un navigateur
Je l'exécute dans le navigateur. Si les résultats de la requête sont des dizaines de milliers, le navigateur le fera. continuez à tourner et cela prendra quatre jours. Plus de dix secondes, 500 données suffisent, 3 ou 4 secondes
.

Je me demande si l'étape result_array() doit être bouclée et prend trop de temps. Il y a des dizaines de milliers d'enregistrements et une vingtaine de champs

.

==============2017-05-16 16:01 update===============

Je n'ai pas utilisé le result_array (fourni avec le framework ci), en regardant la documentation du framework ci, j'ai vu un passage :
Souvent, vous devrez fournir un ID de connexion à la base de données ou un ID de résultat. L'ID de connexion peut être comme ceci
.

$this->db->conn_id;

L'ID du résultat peut être obtenu à partir de l'objet résultat renvoyé par la requête, comme ceci :

$query = $this->db->query("SOME QUERY");
$query->result_id;

J'ai donc modifié mon code pour utiliser result_id pour lire chaque enregistrement dans une boucle

$sql ="select xxx";
$query=$this->db->query($sql);
//Parce qu'ici je j'utilise sqlsrv, donc j'utilise sqlsrv_fetch_array pour lire chaque ligne dans une boucle
//Ensuite, écrivez un fichier csv après chaque ligne read
while($row=sqlsrv_fetch_array($query->result_id,SQLSRV_FETCH_ASSOC)){
// Voici le code pour écrire la ligne dans le fichier csv
}

Le code spécifique est ci-dessous

$sql="xxx";
$query=$this->db->query($sql);
$filename= "CostDetail.csv";//导出的文件名
header('Content-Type: application/vnd.ms-excel');
header('Content-Disposition: attachment;filename="'.$filename.'"');
header('Cache-Control: max-age=0');

// 打开PHP文件句柄,php://output 表示直接输出到浏览器
$fp = fopen('php://output', 'a');

// 输出Excel列名信息
$head = array(xxx);
foreach ($head as $i => $v) {
    // CSV的Excel支持GBK编码,一定要转换,否则乱码
    $head[$i] = iconv('utf-8', 'gbk', $v);
}

// 将数据通过fputcsv写到文件句柄
fputcsv($fp, $head);

// 计数器
$cnt = 0;
// 从数据库中获取数据,为了节省内存,不要把数据一次性读到内存,从句柄中一行一行读即可
$limit = 5000;

while ($row=sqlsrv_fetch_array($query->result_id,SQLSRV_FETCH_ASSOC)){
    $cnt ++;
    if ($limit == $cnt) { //刷新一下输出buffer,防止由于数据过多造成问题
        ob_flush();
        flush();
        $cnt = 0;
    }
    //这里是把每个字段的编码转成gbk
    $newRow[] = $this->_mb_convert_encoding($row['edis_orgsoid']);
    ....    
    unset($row);
    fputcsv($fp, $newRow);
    unset($newRow);
}

exit;

De cette façon, le fichier peut être exporté, mais j'ai regardé le fichier csv avec 19204 lignes et 16 colonnes, soit environ 3 Mo. L'exportation prend 40 à 45 secondes. Je veux demander si ce temps peut être optimisé plus rapidement

.

怪我咯怪我咯2756 Il y a quelques jours775

répondre à tous(2)je répondrai

  • 大家讲道理

    大家讲道理2017-05-17 09:57:57

    Voici comment exporter toutes les données vers Excel. Les données doivent être extraites avant de pouvoir être écrites dans Excel. J'utilise généralement un processus en arrière-plan pour les exporter, puis les envoyer par e-mail

    .

    répondre
    0
  • 给我你的怀抱

    给我你的怀抱2017-05-17 09:57:57

    Fournissez quelques idées :

    • Le front-end doit avoir le choix entre plusieurs plages de temps. Le back-end exécute régulièrement des tâches en fonction de ces plages de temps pour obtenir la base de données et la placer sur le serveur sous forme de fichier statique et lier un champ modifié par l'heure ;

    • Chaque fois que la table est ajoutée, supprimée ou modifiée, la tâche de mise à jour planifiée sera déclenchée ; la mise à jour de la tâche planifiée peut également être effectuée pendant les périodes où le nombre de clients est relativement faible chaque jour, comme la nuit ;
    • A chaque fois que vous exportez, par comparaison

      , s'ils sont identiques, vous pouvez reprendre à l'avance les fichiers statiques précédemment exportés. S'ils ne sont pas égaux, vous devez les mettre à jour sur place, mais cette situation devrait être relativement rare.
    • timemodifiedCette opération de récupération des données de la base de données n'affectera pas l'utilisation des clients. J'espère qu'elle pourra vous aider

      .
    • répondre
      0
  • Annulerrépondre