Редакция кода приложения для уменьшения нет. попаданий в базу данных с точки зрения производительности - PullRequest
1 голос
/ 12 марта 2010

Сценарий

Я хочу проанализировать большой CSV-файл и вставить данные в базу данных, CSV-файл содержит приблизительно 100 тыс. Строк данных.

В настоящее время я использую fgetcsv для разбора файла строка за строкой и вставки данных в базу данных, и поэтому сейчас я беру базу данных для каждой строки данных, присутствующих в файле CSV, поэтому в настоящее время счетчик обращений к базе данных составляет 100 КБ, что не хорошо с точки зрения производительности.

Текущий код:

public function initiateInserts()
{
    //Open Large CSV File(min 100K rows) for parsing.
    $this->fin = fopen($file,'r') or die('Cannot open file');

    //Parsing Large CSV file to get data and initiate insertion into schema.
    while (($data=fgetcsv($this->fin,5000,";"))!==FALSE)
    {
        $query = "INSERT INTO dt_table (id, code, connectid, connectcode) 
                 VALUES (:id, :code, :connectid, :connectcode)";

        $stmt = $this->prepare($query);
        // Then, for each line : bind the parameters
        $stmt->bindValue(':id', $data[0], PDO::PARAM_INT);
        $stmt->bindValue(':code', $data[1], PDO::PARAM_INT);
        $stmt->bindValue(':connectid', $data[2], PDO::PARAM_INT);
        $stmt->bindValue(':connectcode', $data[3], PDO::PARAM_INT);

        // Execute the statement
        $stmt->execute();
        $this->checkForErrors($stmt);
    }
}

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

Любые предложения !!!

Примечание: Это точный пример кода, который я использую, но CSV-файла больше нет. поля, а не только идентификатор, код, connectctid и connectcode, но я хотел убедиться, что я могу объяснить логику и поэтому использовал этот пример кода здесь.

Спасибо !!!

Ответы [ 3 ]

1 голос
/ 12 марта 2010

в вашем цикле while создает только строку запроса и выполняет инструкцию вне цикла. Так что-то вроде этого должно работать (не уверен насчет синтаксиса, так как я уже давно писал php, но он должен работать:

public function initiateInserts()
{
    //Open Large CSV File(min 100K rows) for parsing.
    $this->fin = fopen($file,'r') or die('Cannot open file');

    //Parsing Large CSV file to get data and initiate insertion into schema.
    $query = "";
    while (($data=fgetcsv($this->fin,5000,";"))!==FALSE)
    {
        $query = $query . "INSERT INTO dt_table (id, code, connectid, connectcode) 
                 VALUES (" . $data[0] . ", " . $data[1] . ", " . $data[2] . ", " . $data[3] . ")";
    }
     $stmt = $this->prepare($query);
     // Execute the statement
     $stmt->execute();
     $this->checkForErrors($stmt);
}
0 голосов
/ 14 марта 2010

Я думаю, что смысл подготовленных операторов, помимо безопасности при построении запросов, заключается в том, чтобы «подготовить один раз, выполнить много»: подготовленные операторы предназначены для многократного выполнения.

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

0 голосов
/ 12 марта 2010

Я не могу предложить решение, так как я не делаю PHP.

Но вы можете хранить эти строки в одном массиве и отправлять данные на BD большими партиями по 100 штук.

Что-то вроде Conn.Execute (assemblydInsert), где assemblydInsert - это ToString массива вставок.

Держите соединение открытым в течение всего процесса и используйте только это.

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