PHP Oracle запрос выбора внутри цикла медленно - PullRequest
0 голосов
/ 26 февраля 2019

У меня есть эта функция php для проверки и вставки данных из текстового файла в базу данных.

//Get All Model
$qModel = oci_parse($c1, "SELECT MODELID, MODEL_NAME FROM MEP_TBL_MODEL WHERE ACTIVE = 'Y' AND LOCATION = 'PCBA' ORDER BY MODELID ASC");
oci_execute($qModel);
while($dModel = oci_fetch_array($qModel))
{
    //Configuration
    $qDtl = oci_parse($c1, "SELECT * FROM MEP_TBL_MODEL_CONFIGURATION WHERE MODELID_FK = '" . $dModel['MODELID'] . "'");
    oci_execute($qDtl);
    while($dDtl = oci_fetch_array($qDtl))
    {
        $modelIDAccept[] = $dDtl['CONFIGURATIONID'];
        $dateCode = date($dDtl['DATE_CODE']);
        $readRowAfter = date($dDtl['READ_ROW_AFTER']);
        $createFromFormat = $dDtl['CREATE_FROM_FORMAT'];
        $ipAddress = $dDtl['IP_ADDRESS'];
        $status = $dDtl['STATUS'];

        if($dDtl['SOURCE'] != "")
        {
            $source = "\\".$dDtl['SOURCE'];
        }
        else
        {
            $source = "";
        }

        if(empty($ipAddress))
        {
            $fileAccept = file_get_contents("\\\\192.168.184.13\\Reports\\".$dModel['MODEL_NAME'].$source."\\Accept\\Accept_".$dDtl['MODEL_CODE']."_".$dateCode."_".$dDtl['TS_CODE'].".txt");

            $linesAccept = explode("\n",$fileAccept);
            $rowsintimespanAccept = 0;

            for($i = $readRowAfter; $i < count($linesAccept); $i++)
            {
                $dateobjAccept = DateTime::createFromFormat($createFromFormat, $linesAccept[$i]);

                if($dateobjAccept < $toDateTime && $dateobjAccept > $fromDateTime)
                {
                    $rowsintimespanAccept++;

                    $logDate = $dateobjAccept->format('Y-m-d H:i:s');

                    //I put select query and insert here but it so slow.
                    $qChk = oci_parse($c1, "SELECT * FROM MEP_TBL_OUTPUT_DETAILS WHERE MODELID_FK = '" . $dModel['MODELID'] . "' AND RUNNING_DATE = TO_DATE('$logDate', 'YYYY-MM-DD hh24:mi:ss') AND TS_CODE = '" . $dDtl['TS_CODE'] . "' AND SHIFT = 'Morning' AND QUANTITY_STATUS = 'OK' AND CONFIGURATIONID_FK = '" . $dDtl['CONFIGURATIONID'] . "'");
                    oci_execute($qChk);
                    if(oci_fetch($qChk) > 0)
                    {
                    }
                    else
                    {
                        $qInsert = oci_parse($c1, "INSERT INTO MEP_TBL_OUTPUT_DETAILS(MODELID_FK, RUNNING_DATE, QUANTITY_STATUS, TS_CODE, SHIFT, CONFIGURATIONID_FK) VALUES('" . $dModel['MODELID'] . "', TO_DATE('$logDate', 'YYYY-MM-DD hh24:mi:ss'), 'OK', '" . $dDtl['TS_CODE'] . "', 'Morning', '" . $dDtl['CONFIGURATIONID'] . "')");
                        oci_execute($qInsert);
                    }
                }
            }

            $totalAccept[] = $rowsintimespanAccept;
        }
    }
}

Когда я пытался запустить код, у меня была очень медленная загрузка страницы, и иногда она отображала время ожиданиявыполнение.

Мой вопрос, есть ли способ сделать запрос быстрым, возможно, внутри или вне цикла?Я знал, что это медленно, потому что когда я удаляю запрос выбора и вставки, страница загрузки занимает всего 3-4 секунды.

1 Ответ

0 голосов
/ 26 февраля 2019

Если я правильно прочитал ваш код, то вам нужен только один оператор MERGE, который вы можете запустить в базе данных.Я не знаю PHP, поэтому я не могу дать вам, как он должен называться, но я могу дать вам оператор SQL для запуска:

MERGE INTO mep_tbl_output_details tgt
  USING (SELECT mtm.modelid,
                mtm.model_name,
                mtmc.configurationid,
                mtmc.date_code,
                mtmc.read_row_after,
                mtmc.create_from_format,
                mtmc.ip_address,
                mtmc.status,
                mtmc.ts_code
         FROM   mep_tbl_model mtm
                INNER JOIN mep_tbl_model_configuration mtmc ON mtm.modelid = mtmc.modelid_fk
         WHERE  mtm.active = 'Y'
         AND    mtm.location = 'PCBA') src
    ON (tgt.modelid_fk = src.modelid
        AND tgt.ts_code = src.ts_code
        AND tgt.configurationid_fk = src.configurationid
        AND tgt.runningdate = :log_date
        AND tgt.shift = 'Morning'
        AND tgt.quantity_status = 'OK')
WHEN NOT MATCHED THEN
  INSERT (tgt.modelid_fk, tgt.running_date, tgt.quantity_status, tgt.ts_code, tgt.shift, tgt.configuration_fk)
  VALUES (src.modelid, :log_date, 'OK', src.ts_code, 'Morning', src.configurationid);

Это соединение, которое вы заново изобретали с вашими циклами, связывает его с таблицей, в которую вы пытаетесь вставить, и вставляет строку, только если она еще не существует в таблице.

Вам потребуется написать PHP-код для выполнения этого, имеяпередал log_date как переменную связывания.

Связывая переменную, вы позволяете базе данных пропустить жесткий анализ (то есть выяснение наилучшего способа выполнения запроса), что экономит время.

Не извлекая данные и не зацикливая их вручную перед выбором дополнительных данных и решая, нужно ли вам вставлять данные, вы пропускаете много переключений контекста и извлекаете / проталкиваете данные по сети.Позвольте базе данных сделать тяжелую работу;это то, для чего он предназначен!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...