삽입 명령을 사용하여 PHP를 통해 큰 데이터 세트를 MySQL 테이블에 전달하고 1 마일 길이의 문자열 끝에 각 값을 추가 한 다음 쿼리를 통해 한 번에 약 1000 행을 삽입 할 수 있는지 궁금합니다. 그것을 실행. CodeIgniter 프레임 워크를 사용하고 있으므로 해당 기능도 사용할 수 있습니다.
삽입 명령을 사용하여 PHP를 통해 큰 데이터 세트를 MySQL 테이블에 전달하고 1 마일 길이의 문자열 끝에 각 값을 추가 한 다음 쿼리를 통해 한 번에 약 1000 행을 삽입 할 수 있는지 궁금합니다. 그것을 실행. CodeIgniter 프레임 워크를 사용하고 있으므로 해당 기능도 사용할 수 있습니다.
답변:
INSERT
MySQL에서 여러 행으로 하나의 명령문을 구성하는 것이 INSERT
행당 하나의 명령문 보다 훨씬 빠릅니다 .
즉, PHP에서 문자열 처리 문제가 발생하는 것처럼 들립니다. 실제로 언어 문제가 아니라 알고리즘 문제입니다. 기본적으로 큰 문자열로 작업 할 때 불필요한 복사를 최소화하려고합니다. 기본적으로 이는 연결을 피하려고 함을 의미합니다. 한 번에 수백 개의 행을 삽입하는 것과 같이 큰 문자열을 작성하는 가장 빠르고 메모리 효율적인 방법은 implode()
함수 및 배열 할당 을 이용하는 것입니다 .
$sql = array();
foreach( $data as $row ) {
$sql[] = '("'.mysql_real_escape_string($row['text']).'", '.$row['category_id'].')';
}
mysql_query('INSERT INTO table (text, category) VALUES '.implode(',', $sql));
이 방법의 장점은 지금까지 결합한 SQL 문을 각 연결로 복사하고 다시 복사하지 않는다는 것입니다. 대신, PHP는 명령문 에서 이것을 한 번 수행 implode()
합니다. 이것은 큰 승리입니다.
조합 할 열이 많고 하나 이상이 매우 긴 경우 동일한 작업을 수행하기 위해 내부 루프를 작성 implode()
하고 values 절을 외부 배열에 할당하는 데 사용할 수도 있습니다 .
mysql_real_escape_string
와 mysqli_real_escape_string
와 mysql_query
와 mysqli_query
내가 MySQLi를 사용하고 있는데 이러한 PHP5의로 사용되지 않습니다있다. 많은 감사합니다!
mysql_*
PHP에서 제거되었으므로 mysqli_*
인터페이스 를 사용해야합니다 .
codeigniter에서 다중 삽입 / 배치 삽입을 지원합니다. 나는 같은 문제가 있었다. 질문에 대답하기에는 너무 늦었지만 누군가를 도울 것입니다. 이것이 바로이 질문에 답하는 이유입니다.
$data = array(
array(
'title' => 'My title' ,
'name' => 'My Name' ,
'date' => 'My date'
),
array(
'title' => 'Another title' ,
'name' => 'Another Name' ,
'date' => 'Another date'
)
);
$this->db->insert_batch('mytable', $data);
// Produces: INSERT INTO mytable (title, name, date) VALUES ('My title', 'My name', 'My date'), ('Another title', 'Another name', 'Another date')
mysqli_stmt 클래스를 사용하여 하나의 행을 삽입하기 위해 쿼리를 준비한 다음 데이터 배열을 반복 할 수 있습니다. 다음과 같은 것 :
$stmt = $db->stmt_init();
$stmt->prepare("INSERT INTO mytbl (fld1, fld2, fld3, fld4) VALUES(?, ?, ?, ?)");
foreach($myarray as $row)
{
$stmt->bind_param('idsb', $row['fld1'], $row['fld2'], $row['fld3'], $row['fld4']);
$stmt->execute();
}
$stmt->close();
여기서 'idsb'는 바인딩하는 데이터 유형입니다 (int, double, string, blob).
나는 이것이 오래된 쿼리라는 것을 알고 있지만, 나는 단지 읽고 있었고 다른 곳에서 찾은 것을 추가 할 것이라고 생각했다.
PHP 5의 mysqli는 위의 답변에 대한 삽입 시간을 단축 할 수있는 좋은 기능을 갖춘 ojbect입니다.
$mysqli->autocommit(FALSE);
$mysqli->multi_query($sqlCombined);
$mysqli->autocommit(TRUE);
많은 행을 삽입 할 때 자동 커밋을 끄면 삽입 속도가 빨라지므로 끄고 위에서 언급 한대로 실행하거나 세미 콜론으로 구분 된 많은 삽입 문 인 문자열 (sqlCombined)을 만들면 다중 쿼리가 잘 처리됩니다.
이것이 누군가가 시간을 절약하는 데 도움이되기를 바랍니다 (검색 및 삽입!)
아르 자형
항상 mysql을 사용할 수 있습니다 LOAD DATA
:
LOAD DATA LOCAL INFILE '/full/path/to/file/foo.csv' INTO TABLE `footable` FIELDS TERMINATED BY ',' LINES TERMINATED BY '\r\n'
많은 INSERT
명령문을 사용하지 않고 대량 삽입을 수행 합니다.
LOCAL
비트를 제거하십시오 .
글쎄, 당신은 1000 개의 쿼리 호출을 실행하고 싶지 않지만 이것을하는 것이 좋습니다 :
$stmt= array( 'array of statements' );
$query= 'INSERT INTO yourtable (col1,col2,col3) VALUES ';
foreach( $stmt AS $k => $v ) {
$query.= '(' .$v. ')'; // NOTE: you'll have to change to suit
if ( $k !== sizeof($stmt)-1 ) $query.= ', ';
}
$r= mysql_query($query);
데이터 소스에 따라 배열을 채우는 것은 파일을 열고를 통해 배열에 내용을 덤프하는 것만 큼 쉽습니다 file()
.
codeigniter에서 여러 가지 방법으로 할 수 있습니다.
첫 번째 루프
foreach($myarray as $row)
{
$data = array("first"=>$row->first,"second"=>$row->sec);
$this->db->insert('table_name',$data);
}
두 번째 -삽입 배치
$data = array(
array(
'first' => $myarray[0]['first'] ,
'second' => $myarray[0]['sec'],
),
array(
'first' => $myarray[1]['first'] ,
'second' => $myarray[1]['sec'],
),
);
$this->db->insert_batch('table_name', $data);
세 번째 방법-다중 값 전달
$sql = array();
foreach( $myarray as $row ) {
$sql[] = '("'.mysql_real_escape_string($row['first']).'", '.$row['sec'].')';
}
mysql_query('INSERT INTO table (first, second) VALUES '.implode(',', $sql));
이 질문에 대답하기에는 너무 늦었지만. 여기에 같은 대답이 있습니다.
CodeIgniter를 사용하는 경우 query_builder 클래스에 정의 된 내장 메소드를 사용할 수 있습니다.
$ this-> db-> insert_batch ()
제공 한 데이터를 기반으로 삽입 문자열을 생성하고 쿼리를 실행합니다. 배열이나 객체를 함수에 전달할 수 있습니다. 다음은 배열을 사용하는 예입니다.
$data = array(
array(
'title' => 'My title',
'name' => 'My Name',
'date' => 'My date'
),
array(
'title' => 'Another title',
'name' => 'Another Name',
'date' => 'Another date'
)
);
$this->db->insert_batch('mytable', $data);
// Produces: INSERT INTO mytable (title, name, date) VALUES ('My title', 'My name', 'My date'), ('Another title', 'Another name', 'Another date')
첫 번째 매개 변수는 테이블 이름을 포함하고 두 번째 매개 변수는 값의 연관 배열입니다.
다음과 같이 사용되는 여러 줄을 수행하는 클래스를 만들었습니다.
$pdo->beginTransaction();
$pmi = new PDOMultiLineInserter($pdo, "foo", array("a","b","c","e"), 10);
$pmi->insertRow($data);
// ....
$pmi->insertRow($data);
$pmi->purgeRemainingInserts();
$pdo->commit();
여기서 클래스는 다음과 같이 정의됩니다.
class PDOMultiLineInserter {
private $_purgeAtCount;
private $_bigInsertQuery, $_singleInsertQuery;
private $_currentlyInsertingRows = array();
private $_currentlyInsertingCount = 0;
private $_numberOfFields;
private $_error;
private $_insertCount = 0;
/**
* Create a PDOMultiLine Insert object.
*
* @param PDO $pdo The PDO connection
* @param type $tableName The table name
* @param type $fieldsAsArray An array of the fields being inserted
* @param type $bigInsertCount How many rows to collect before performing an insert.
*/
function __construct(PDO $pdo, $tableName, $fieldsAsArray, $bigInsertCount = 100) {
$this->_numberOfFields = count($fieldsAsArray);
$insertIntoPortion = "REPLACE INTO `$tableName` (`".implode("`,`", $fieldsAsArray)."`) VALUES";
$questionMarks = " (?".str_repeat(",?", $this->_numberOfFields - 1).")";
$this->_purgeAtCount = $bigInsertCount;
$this->_bigInsertQuery = $pdo->prepare($insertIntoPortion.$questionMarks.str_repeat(", ".$questionMarks, $bigInsertCount - 1));
$this->_singleInsertQuery = $pdo->prepare($insertIntoPortion.$questionMarks);
}
function insertRow($rowData) {
// @todo Compare speed
// $this->_currentlyInsertingRows = array_merge($this->_currentlyInsertingRows, $rowData);
foreach($rowData as $v) array_push($this->_currentlyInsertingRows, $v);
//
if (++$this->_currentlyInsertingCount == $this->_purgeAtCount) {
if ($this->_bigInsertQuery->execute($this->_currentlyInsertingRows) === FALSE) {
$this->_error = "Failed to perform a multi-insert (after {$this->_insertCount} inserts), the following errors occurred:".implode('<br/>', $this->_bigInsertQuery->errorInfo());
return false;
}
$this->_insertCount++;
$this->_currentlyInsertingCount = 0;
$this->_currentlyInsertingRows = array();
}
return true;
}
function purgeRemainingInserts() {
while ($this->_currentlyInsertingCount > 0) {
$singleInsertData = array();
// @todo Compare speed - http://www.evardsson.com/blog/2010/02/05/comparing-php-array_shift-to-array_pop/
// for ($i = 0; $i < $this->_numberOfFields; $i++) $singleInsertData[] = array_pop($this->_currentlyInsertingRows); array_reverse($singleInsertData);
for ($i = 0; $i < $this->_numberOfFields; $i++) array_unshift($singleInsertData, array_pop($this->_currentlyInsertingRows));
if ($this->_singleInsertQuery->execute($singleInsertData) === FALSE) {
$this->_error = "Failed to perform a small-insert (whilst purging the remaining rows; the following errors occurred:".implode('<br/>', $this->_singleInsertQuery->errorInfo());
return false;
}
$this->_currentlyInsertingCount--;
}
}
public function getError() {
return $this->_error;
}
}
나는 당신이 쉽게 사용할 수있는이 간단한 기능을 만들었습니다. 삽입 데이터 data array에 대해 table-name ($tbl)
테이블 필드 를 전달해야합니다 .($insertFieldsArr)
($arr)
insert_batch('table',array('field1','field2'),$dataArray);
function insert_batch($tbl,$insertFieldsArr,$arr){ $sql = array();
foreach( $arr as $row ) {
$strVals='';
$cnt=0;
foreach($insertFieldsArr as $key=>$val){
if(is_array($row)){
$strVals.="'".mysql_real_escape_string($row[$cnt]).'\',';
}
else{
$strVals.="'".mysql_real_escape_string($row).'\',';
}
$cnt++;
}
$strVals=rtrim($strVals,',');
$sql[] = '('.$strVals.')';
}
$fields=implode(',',$insertFieldsArr);
mysql_query('INSERT INTO `'.$tbl.'` ('.$fields.') VALUES '.implode(',', $sql));
}