suchen

Heim  >  Fragen und Antworten  >  Hauptteil

Die von der PHP-Abfrage zurückgegebenen Daten sind zu groß und der Import von CSV-Dateien ist sehr langsam.

Das Framework verwendet ci und die Datenbank ist sqlsrv (SQL Server 2008). Die Ausführung dieser SQL-Anweisung im CI-Framework dauert 30 Sekunden Rotieren Sie 20.000 Daten. Es geht um Sekunden, aber meine SQL-Anweisung wird in SQL Server 2008 R2 in Sekunden ausgeführt. Wenn ich die integrierte SQL-Abfrage in CI verwende, beträgt die Ausführungszeit 200 Millisekunden, was bedeutet, dass meine Anweisung nicht ausgeführt wird langsam. Persönlich denke ich, dass es zu langsam ist, weil es zu viele Daten und etwa 20 Felder zurückgibt. Da ich Statistiken erstelle und die Daten in eine CSV-Datei exportiere, gibt es viele Daten Ich kümmere mich darum?
Meine SQL-Anweisung ist „select * from table where create_time“ zwischen „xxxx-xx-xx 00:00:00“ und „xxxx-xx-xx 23:59:59“. Sie basiert auf dem Zeitraum, wenn der Benutzer die auswählt Zeit: Wenn der Bereich klein ist, werden die Daten kleiner sein. Wenn der Bereich groß ist, werden die Daten groß sein. Wenn die Daten groß sind, werden sie sehr langsam sein

öffentliche Funktion 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();

}

Dies ist bereits die einfachste Abfrage. Die SQL-Anweisung kann in Sekundenschnelle überprüft werden, die Ausführung mit einem Browser ist jedoch sehr langsam.
Wenn die Abfrageergebnisse Zehntausende betragen, wird dies der Fall sein Weiterdrehen und es dauert mehr als zehn Sekunden, 500 Daten reichen aus, 3 oder 4 Sekunden
Ich frage mich, ob der Schritt result_array() in einer Schleife ausgeführt werden muss und zu viel Zeit in Anspruch nimmt. Es gibt Zehntausende von Datensätzen und es gibt zwanzig Felder

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

Ich habe das mitgelieferte result_array( nicht verwendet Als ich mir die Dokumentation zum Ci-Framework ansah, sah ich eine Passage:

Oft müssen Sie eine Datenbankverbindungs-ID oder eine Ergebnis-ID angeben. Die Verbindungs-ID kann so sein

$this->db->conn_id;
Die
Ergebnis-ID kann wie folgt aus dem von der Abfrage zurückgegebenen Ergebnisobjekt abgerufen werden:
$query = $this->db->query("SOME QUERY");
$query->result_id;

Also habe ich meinen Code geändert, um result_id zu verwenden, um jeden Datensatz in einer Schleife zu lesen

$sql ="select xxx";

$query=$this->db->query($sql);

//Weil hier ich verwende sqlsrv, also verwende ich sqlsrv_fetch_array, um jede Zeile in einer Schleife zu lesen
//Dann schreibe eine CSV-Datei nach jeder gelesenen Zeile
while($row=sqlsrv_fetch_array($query->result_id,SQLSRV_FETCH_ASSOC)){
// Hier ist der Code zum Schreiben einer Zeile in eine CSV-Datei
}

Der spezifische Code ist unten

$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;

Auf diese Weise kann die Datei exportiert werden, aber ich habe mir die CSV-Datei mit 19204 Zeilen und 16 Spalten angesehen, die etwa 40-45 Sekunden dauert. Ich möchte fragen, ob diese Zeit schneller optimiert werden kann
怪我咯怪我咯2757 Tage vor781

Antworte allen(2)Ich werde antworten

  • 大家讲道理

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

    这种要把所有数据导出到excel是这样的。数据要查出来才能写入excel,这种我一般用后台进程导出之后发邮箱

    Antwort
    0
  • 给我你的怀抱

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

    提供一点思路:

    • 前端应该有几个时间范围选择,后端根据这些时间范围定时跑任务去数据库获取放在服务器上作为静态文件并且绑定一个timemodified字段;

    • 每次该表增加、删除或者修改后也要触发更新定时任务;也可以在每天客户量比较少的时段比如夜里做定时任务更新;

    • 每次导出的时候,通过比对timemodified,如果相同则可以将之前导出的静态文件提前拿过来,如果不等则需要现场更新,不过这种情况应该比较少;

    这样去数据库取数据的操作不会影响客户的使用,希望能帮助到你

    Antwort
    0
  • StornierenAntwort