tp 框架的insertAll 解讀

有這樣一個表

CREATE TABLE IF NOT EXISTS `user_info` (
 `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增主鍵',
 `name` varchar(255) NOT NULL default '' COMMENT '姓名',
 `age` int(11) NOT NULL default '0' COMMENT '年齡',
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用戶信息表';

批量插入

方法一、使用for循環插入

在往mysql插入少量數據的時候,我們一般用foreach或者(for)循環

$arr = [    
    [
        'name' => 'name1',
        'age' => 18,
    ],
    [
        'name' => 'name2',
        'age' => 19,
    ],
    [
        'name' => 'name3',
        'age' => 18,
    ],
];
foreach($arr as $key=>$values){
    //這裏是tp5.0的寫法
    Db::name('user_info')->insert($values);
}

假如說要批量插入大量數據,如果還用foreach或者(for)循環的辦法插入是沒有問題的,只是時間會比較長。不過有時超出php代碼執行時間,會出現中斷

對比一下插入少量數據與插入大量數據,使用上面的foreach或者(for)循環插入耗費的時間:當然這也是粗略計算時間

條數 時間(單位:秒)
10 0.011
1000 0.585
10000 5.733
100000 60.587

 

方法二、使用insert語句合併插入

mysql裏面是可以使用insert語句進行合併插入的,比如
INSERT INTO user_info (name, age) VALUES ('name1', 18), ('name2', 19);表示一次插入兩條數據

$arr = [    
    [
        'name' => 'name1',
        'age' => 18,
    ],
    [
        'name' => 'name2',
        'age' => 19,
    ],
    [
        'name' => 'name3',
        'age' => 18,
    ],
];
 Db::name('user_info')->insertAll($values);

 下面看一下少量數據與大量數據的時間對比。從總體時間上,可以看出insert合併插入比剛纔for循環插入節約了很多時間,效果很明顯

條數 時間(單位:秒)
10 0.006
1000 0.025
10000 0.131
100000 1.23

 以下是對insertAll分析

/**
     * 批量插入記錄
     * @access public
     * @param mixed     $dataSet 數據集
     * @param boolean   $replace  是否replace
     * @param integer   $limit   每次寫入數據限制
     * @return integer|string
     */
    public function insertAll(array $dataSet, $replace = false, $limit = null)
    {
        // 分析查詢表達式
        $options = $this->parseExpress();
        if (!is_array(reset($dataSet))) {
            return false;
        }

        // 生成SQL語句
        if (is_null($limit)) {
        //array_chunk將數組切成指定大小的塊,然後對每個塊進行insert合併插入.
            $sql = $this->builder->insertAll($dataSet, $options, $replace);
        } else {
            $array = array_chunk($dataSet, $limit, true);
            foreach ($array as $item) {
                $sql[] = $this->builder->insertAll($item, $options, $replace);
            }
        }

        // 獲取參數綁定
        $bind = $this->getBind();
        if ($options['fetch_sql']) {
            // 獲取實際執行的SQL語句
            return $this->connection->getRealSql($sql, $bind);
        } elseif (is_array($sql)) {
            // 執行操作
            return $this->batchQuery($sql, $bind, $this);
        } else {
            // 執行操作
            return $this->execute($sql, $bind, $this);
        }
    }

 若想你的代碼高效,最好用方式2,執行時間短

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章