【发布时间】:2022-01-22 09:02:18
【问题描述】:
我是一名初级开发人员,我遇到了脚本循环问题。 循环循环大数组来自数据库。 问题是在最短的时间内完成循环是可能的,但目前,大约 500 个元素需要 15 分钟才能完成。 这是不可接受的。 我的文件类型需要引号中的空格。 这是私有类函数中的代码:
$length = count($this->fileH1);
for ($z = 0; $z < $length; $z++) {
$this->fileH2[$z]['id_paziente'] = $this->fileH1[$z]->id_paziente;
$this->fileH2[$z]['regione'] = decifra($_SESSION['cod_regione']);
$this->fileH2[$z]['asl'] = decifra($_SESSION['cod_asl']);
$this->fileH2[$z]['cod_struttura'] = decifra($_SESSION['cod_struttura']);
$this->fileH2[$z]['tipo_assist'] = "RIA";
$this->fileH2[$z]['tipo_strutt'] = decifra($_SESSION['tipo_struttura']);
// CERCO LE INFO DELLE MENOMAZIONI DEL PAZIENTE
$stmt_get_info_menomazioni = $this->centro->prepare('SELECT codice, icd9_nuovo FROM tbl_pazienti_terapie_menomazioni WHERE id_paziente = ? AND id_contratto = ? LIMIT 1');
$stmt_get_info_menomazioni->bind_param("ii", $this->fileH1[$z]->id_paziente, $this->fileH1[$z]->id_contratto); //$fileH1[$z]['id_terapia']);
$stmt_get_info_menomazioni->execute();
$stmt_get_info_menomazioni->store_result();
$stmt_get_info_menomazioni->bind_result($cod_menomazione, $icd9_menomazione);
if ($stmt_get_info_menomazioni->num_rows > 0) {
$stmt_get_info_menomazioni->fetch();
if ($cod_menomazione !== NULL || $cod_menomazione !== '')
$this->fileH2[$z]['cod_menomazione'] = $cod_menomazione;
else $this->fileH2[$z]['cod_menomazione'] = ' ';
if ($icd9_menomazione !== NULL || $icd9_menomazione !== '')
$this->fileH2[$z]['icd9_menomazione'] = str_pad($icd9_menomazione, 10, " ");
else $this->fileH2[$z]['icd9_menomazione'] = ' ';
} else {
$this->fileH2[$z]['cod_menomazione'] = ' ';
$this->fileH2[$z]['icd9_menomazione'] = ' ';
}
$stmt_get_info_menomazioni->close();
$this->fileH2[$z]['num_registro'] = $this->fileH1[$z]->anno_rif . decifra($_SESSION['cod_asl']) . '0' . date('y') . str_pad($_POST['mese'], 2, '0', STR_PAD_LEFT) . '0001';; // "203021040001"; // AGGIUNGERE numero registro struttura
$this->fileH2[$z]['medico_autorizz'] = ' ';
$this->fileH2[$z]['cod_medico_autorizz'] = ' ';
$this->fileH2[$z]['istat_primo_ricovero'] = '000000';
$this->fileH2[$z]['progressivo'] = $this->fileH1[$z]->progressivo;
// CERCO LE INFO DELLE TERAPIE DEL PAZIENTE
$stmt_get_info_menomazioni = $this->centro->prepare('SELECT data_autorizz, data_inizio, data_fine FROM tbl_pazienti_contratti WHERE id_paziente = ? AND id = ? LIMIT 1');
$stmt_get_info_menomazioni->bind_param("ii", $this->fileH1[$z]->id_paziente, $this->fileH1[$z]->id_contratto); //$fileH1[$z]['id_terapia']);
$stmt_get_info_menomazioni->execute();
$stmt_get_info_menomazioni->store_result();
$stmt_get_info_menomazioni->bind_result($data_autorizz, $data_inizio, $data_fine);
if ($stmt_get_info_menomazioni->num_rows > 0) {
$stmt_get_info_menomazioni->fetch();
if ($data_autorizz !== NULL || $data_autorizz !== '0000-00-00') $this->fileH2[$z]['data_prescrizione'] = date('dmY', strtotime($data_autorizz)); else $this->fileH2[$z]['data_prescrizione'] = ' ';
if ($data_inizio !== NULL || $data_inizio !== '0000-00-00') $this->fileH2[$z]['data_inizio_terapia'] = date('dmY', strtotime($data_inizio)); else $this->fileH2[$z]['data_inizio_terapia'] = ' ';
if ($data_fine !== NULL || $data_fine !== '0000-00-00') $this->fileH2[$z]['data_fine_terapia'] = date('dmY', strtotime($data_fine)); else $this->fileH2[$z]['data_fine_terapia'] = ' ';
// CALCOLO LE DATE DEL CICLO DI FATTURAZIONE
$data_inizio_mese_attuale = date('Y-m-1');
$data_inizio_terapia = date('Y-m-d', strtotime($data_inizio));
if ($data_inizio_mese_attuale < $data_inizio_terapia)
$this->fileH2[$z]['data_inizio_periodo_fatturazione'] = date('dmY', strtotime($data_inizio_terapia));
else $this->fileH2[$z]['data_inizio_periodo_fatturazione'] = date('dmY', strtotime($data_inizio_mese_attuale));
$data_fine_mese_attuale = date('Y-m-t'); // t = ultimo gg del mese attuale
$data_fine_terapia = date('Y-m-d', strtotime($data_fine));
if ($data_fine_mese_attuale > $data_fine_terapia)
$this->fileH2[$z]['data_fine_periodo_fatturazione'] = date('dmY', strtotime($data_fine_terapia));
else $this->fileH2[$z]['data_fine_periodo_fatturazione'] = date('dmY', strtotime($data_fine_mese_attuale));
// CALCOLO QTA PRESTAZIONI EFFETTUATE
$stmt_get_qta_prestaz_eff = $this->centro->prepare('SELECT COUNT(id) FROM tbl_pazienti_terapie_presenze WHERE MONTH(DATE(ingresso_effettuato)) = ? AND id_paziente = ?');
$stmt_get_qta_prestaz_eff->bind_param('ii', $this->mese, $this->fileH1[$z]->id_paziente);
$stmt_get_qta_prestaz_eff->execute();
$stmt_get_qta_prestaz_eff->store_result();
$stmt_get_qta_prestaz_eff->bind_result($qta_prestaz);
$stmt_get_qta_prestaz_eff->fetch();
$this->fileH2[$z]['qta_prestaz'] = str_pad($qta_prestaz, 3, "0", STR_PAD_LEFT);
$this->fileH2[$z]['codifica_nomencl'] = 't';
if ($this->fileH2[$z]['progressivo'] == '99')
$this->fileH2[$z]['codice_prestaz'] = ' ';
else $this->fileH2[$z]['codice_prestaz'] = '001.001';
$this->fileH2[$z]['esenzione_1'] = '0';
$this->fileH2[$z]['esenzione_2'] = ' ';
$this->fileH2[$z]['esenzione_3'] = '0';
$this->fileH2[$z]['onere'] = "1";
$this->fileH2[$z]['importo_compart'] = '000000,00';
$this->fileH2[$z]['posizione_compart'] = '0';
if ($this->fileH1[$z]->tariffa !== NULL || $this->fileH1[$z]->tariffa !== '')
$this->fileH2[$z]['importo_totale'] = str_replace('.', ',', str_pad(floatval($this->fileH1[$z]->tariffa) * $qta_prestaz, 9, "0", STR_PAD_LEFT));
else $this->fileH2[$z]['importo_totale'] = " ";
$stmt_get_qta_prestaz_eff->close();
}
$stmt_get_info_menomazioni->close();
$this->fileH2[$z]['posizione_contab'] = ' ';
$this->fileH2[$z]['err01'] = ' ';
$this->fileH2[$z]['err02'] = ' ';
$this->fileH2[$z]['err03'] = ' ';
$this->fileH2[$z]['err04'] = ' ';
$this->fileH2[$z]['err05'] = ' ';
$this->fileH2[$z]['err06'] = ' ';
$this->fileH2[$z]['err07'] = ' ';
$this->fileH2[$z]['err08'] = ' ';
$this->fileH2[$z]['err09'] = ' ';
$this->fileH2[$z]['err10'] = ' ';
$this->fileH2[$z]['anno_rif'] = $this->fileH1[$z]->anno_rif;
$this->fileH2[$z]['cod_strut_erog'] = decifra($_SESSION['cod_struttura_eroga']);
$this->fileH2[$z]['identificativo_mensile'] = $this->fileH1[$z]->identificativo_mensile;
$this->fileH2[$z]['anno_mese_invio'] = date('Ym');
$this->fileH2[$z]['asl_addebito'] = 000;
}
有人可以帮助我吗?
更新 1: 首先感谢大家的回答。 使用 JOIN 进行唯一调用,然后将准备语句移出循环。现在大约 500 个项目的时间是 5 分钟。
$sql = 'SELECT COUNT(tp.id),pc.data_autorizz, pc.data_inizio, pc.data_fine, tm.codice, tm.icd9_nuovo FROM tbl_pazienti_terapie_presenze as tp LEFT JOIN tbl_pazienti_contratti as pc ON tp.id_paziente = pc.id_paziente LEFT JOIN tbl_pazienti_terapie_menomazioni as tm ON tm.id_contratto = pc.id AND tm.id_paziente = pc.id_paziente WHERE MONTH(DATE(tp.ingresso_effettuato)) = ? AND tp.id_paziente = ? AND pc.id = ?';
$do_sql = $this->centro->prepare($sql);
$length = count($this->fileH1);
for ($z = 0; $z < $length; $z++) {
$this->fileH2[$z]['id_paziente'] = $this->fileH1[$z]['id_paziente'];['id_terapia'];
$this->fileH2[$z]['regione'] = decifra($_SESSION['cod_regione']);
$this->fileH2[$z]['asl'] = decifra($_SESSION['cod_asl']);
$this->fileH2[$z]['cod_struttura'] = decifra($_SESSION['cod_struttura']);
$this->fileH2[$z]['tipo_assist'] = "RIA";
$this->fileH2[$z]['tipo_strutt'] = decifra($_SESSION['tipo_struttura']);
$do_sql->bind_param('iii', $this->mese, $this->fileH1[$z]['id_paziente'], $this->fileH1[$z]['id_contratto']);
$do_sql->execute();
$do_sql->store_result();
$do_sql->bind_result($qta_prestaz, $data_autorizz, $data_inizio, $data_fine, $cod_menomazione, $icd9_menomazione);
if ($do_sql->num_rows > 0) {
$do_sql->fetch();
if ($cod_menomazione !== NULL && $cod_menomazione !== '')
$this->fileH2[$z]['cod_menomazione'] = $cod_menomazione;
else $this->fileH2[$z]['cod_menomazione'] = ' ';
if ($icd9_menomazione !== NULL && $icd9_menomazione !== '')
$this->fileH2[$z]['icd9_menomazione'] = str_pad($icd9_menomazione, 10, " ");
else $this->fileH2[$z]['icd9_menomazione'] = ' ';
if ($data_autorizz !== NULL && $data_autorizz !== '0000-00-00') $this->fileH2[$z]['data_prescrizione'] = date('dmY', strtotime($data_autorizz)); else $this->fileH2[$z]['data_prescrizione'] = ' ';
if ($data_inizio !== NULL && $data_inizio !== '0000-00-00') $this->fileH2[$z]['data_inizio_terapia'] = date('dmY', strtotime($data_inizio)); else $this->fileH2[$z]['data_inizio_terapia'] = ' ';
if ($data_fine !== NULL && $data_fine !== '0000-00-00') $this->fileH2[$z]['data_fine_terapia'] = date('dmY', strtotime($data_fine)); else $this->fileH2[$z]['data_fine_terapia'] = ' ';
if ($this->fileH1[$z]['tariffa'] !== NULL || $this->fileH1[$z]['tariffa'] !== '')
$this->fileH2[$z]['importo_totale'] = str_replace('.', ',', str_pad(floatval($this->fileH1[$z]->tariffa) * $qta_prestaz, 9, "0", STR_PAD_LEFT));
else $this->fileH2[$z]['importo_totale'] = ' ';
$this->fileH2[$z]['codifica_nomencl'] = 't';
if ($this->fileH2[$z]['progressivo'] == '99')
$this->fileH2[$z]['codice_prestaz'] = ' ';
else $this->fileH2[$z]['codice_prestaz'] = '001.001';
$this->fileH2[$z]['esenzione_1'] = '0';
$this->fileH2[$z]['esenzione_2'] = ' ';
$this->fileH2[$z]['esenzione_3'] = '0';
$this->fileH2[$z]['onere'] = "1";
$this->fileH2[$z]['importo_compart'] = '000000,00';
$this->fileH2[$z]['posizione_compart'] = '0';
// CALCOLO LE DATE DEL CICLO DI FATTURAZIONE
$data_inizio_mese_attuale = date('Y-m-1');
$data_inizio_terapia = date('Y-m-d', strtotime($data_inizio));
if ($data_inizio_mese_attuale < $data_inizio_terapia)
$this->fileH2[$z]['data_inizio_periodo_fatturazione'] = date('dmY', strtotime($data_inizio_terapia));
else $this->fileH2[$z]['data_inizio_periodo_fatturazione'] = date('dmY', strtotime($data_inizio_mese_attuale));
$data_fine_mese_attuale = date('Y-m-t'); // t = ultimo gg del mese attuale
$data_fine_terapia = date('Y-m-d', strtotime($data_fine));
if ($data_fine_mese_attuale > $data_fine_terapia)
$this->fileH2[$z]['data_fine_periodo_fatturazione'] = date('dmY', strtotime($data_fine_terapia));
else $this->fileH2[$z]['data_fine_periodo_fatturazione'] = date('dmY', strtotime($data_fine_mese_attuale));
$this->fileH2[$z]['num_registro'] = $this->fileH1[$z]['anno_rif'] . decifra($_SESSION['cod_asl']) . '0' . date('y') . str_pad($_POST['mese'], 2, '0', STR_PAD_LEFT) . '0001';; // "203021040001"; // AGGIUNGERE numero registro struttura
$this->fileH2[$z]['medico_autorizz'] = ' ';
$this->fileH2[$z]['cod_medico_autorizz'] = ' ';
$this->fileH2[$z]['istat_primo_ricovero'] = '000000';
$this->fileH2[$z]['progressivo'] = $this->fileH1[$z]['progressivo'];
}
$this->fileH2[$z]['posizione_contab'] = ' ';
$this->fileH2[$z]['err01'] = ' ';
$this->fileH2[$z]['err02'] = ' ';
$this->fileH2[$z]['err03'] = ' ';
$this->fileH2[$z]['err04'] = ' ';
$this->fileH2[$z]['err05'] = ' ';
$this->fileH2[$z]['err06'] = ' ';
$this->fileH2[$z]['err07'] = ' ';
$this->fileH2[$z]['err08'] = ' ';
$this->fileH2[$z]['err09'] = ' ';
$this->fileH2[$z]['err10'] = ' ';
$this->fileH2[$z]['anno_rif'] = $this->fileH1[$z]['anno_rif'];
$this->fileH2[$z]['cod_strut_erog'] = decifra($_SESSION['cod_struttura_eroga']);
$this->fileH2[$z]['identificativo_mensile'] = $this->fileH1[$z]['identificativo_mensile'];
$this->fileH2[$z]['anno_mese_invio'] = date('Ym');
$this->fileH2[$z]['asl_addebito'] = 000;
$do_sql->close();
比以前好,但仍然不能接受
更新 2:
经过一些测试,我发现这个查询COUNT(id) FROM tbl_pazienti_terapie_presenze WHERE MONTH(ingresso_effettuato) = ? AND id_paziente = ? 导致严重减速。我不知道为什么会这样。
解决方案:
谢谢大家的回答。
问题是查询函数 MONTH()。尽管该字段已编入索引,但函数 MONTH() 会跳过索引并因此减慢查询速度。
将其替换为
例如WHERE ingresso_effettuato BETWEEN '2021-12-01 00:00:00', '2021-12-31 23:59:59'
或WHERE ingresso_effettuato >= '2021-12-01 00:00:00' AND ingresso_effettuato <= '2021-12-31 23:59:59' 问题已解决。
【问题讨论】:
-
小点 将 IF 语句塞进一行并不能加快速度,只会减慢跟随你的可怜的开发人员的速度,并且必须弄清楚发生了什么
-
请告诉我们
SHOW KEYS FROM tbl_pazienti_terapie_menomazioni的结果。请为您使用的每张桌子。 -
您尝试过检查哪些部分速度较慢?您尝试过什么来解决问题本身?
-
if (x !== NULL || x != '')的一般逻辑总是正确的。可能意味着使用&&。 -
如果您遇到任何与数据库相关的问题,请分享更多详细信息,例如慢查询的执行计划