保存到 MySQL 的速度慢 (PHP - Yii2)
Low speed of saving to the MySQL (PHP - Yii2)
我正在尝试将数据从 JSON 文件导入到 MySQL。
public function importProductFile($file, $return = true)
{
$products = json_decode($file);
$dubTableName = Product::tableName() . "_dub";
$start = time();
if ($this->db->createDuplicateTable(Product::tableName(), $dubTableName)) {
$i = 0;
foreach ($products as $product) {
$i++;
$item = new Product_dub();
$item->id_1c_product = $product->id;
$category = Category_dub::findOne(['id_1c_category' => $product->category_id]);
if (!$category) {
Answer::failure("В этом товаре отсутствует категория или такой категории не существует: " . $product->title);
}
$item->category_id = $category->id;
$item->title = $product->title;
$brand = Brands_dub::findOne(['id_1c_brand' => $product->brand_id]);
if (!$brand) {
Answer::failure("В этом товаре отсутствует бренд/изготовитель: " . $product->title);
}
$item->brand_id = $brand->id;
// $item->shortdesc = $product->shortdesc;
$item->content1 = $product->content1;
$item->content2 = $product->content2;
$item->content3 = $product->content3;
$item->link_order = $product->link_order;
$item->img = $product->img;
$item->in_stock = $product->in_stock ? 1 : 0;
$item->is_popular = $product->is_popular ? 1 : 0;
if (!$item->save()) {
Answer::failure("Не удалось импортировать: Проверьте данные в " . $product->title);
}
if ($i == 200) {
break;
}
}
}
$finish = time();
$res = $finish - $start . "sec. ";
if ($return) {
echo $res;
Answer::success();
}
}
我的 JSON 文件中大约有 1100 个对象。将 100 行添加到数据库需要 7 秒。添加 200 行 - 15 秒。 300 = 33 秒,400 = 58 秒。为什么它会随着时间的推移变慢以及如何加快这个过程?
我在本地 OpenServer 服务器上做所有事情。
PHP 7.2 版本,至强 2620v3 处理器,16 GB DDR4,硬盘。
UPD 1.
“您能否尝试不导入并仅确定阅读速度”- 我评论 $item->save()
并获得所有 JSON 文件的 1-2 秒。 “在你的循环的每次迭代中,你都是 运行 2 个数据库查询来加载类别和品牌。” - 我试图删除这些行以进行测试 - 但结果比使用 2 个数据库查询快 1-2 秒。
UPD 2.
我将 save()
更改为 insert()
- 速度提高了。现在所有 JSON(1107 行)都在 40 秒内导入。
是否有更快的方法将 JSON 中的现成数据加载到数据库中?
如果有 10 万行或一百万行呢?等几个小时是正常的做法吗?
public function importProductFile($file, $return = true)
{
$products = json_decode($file);
$dubTableName = Product::tableName() . "_dub";
$start = time();
if ($this->db->createDuplicateTable(Product::tableName(), $dubTableName)) {
$start = time();
$categoryMap = Category_dub::find()->select(['id', 'id_1c_category'])->indexBy('id_1c_category')->column();
$brandMap = Brands_dub::find()->select(['id', 'id_1c_brand'])->indexBy('id_1c_brand')->column();
foreach ($products as $product) {
Yii::$app->db->createCommand()->insert('product_dub', [
'id_1c_product' => $product->id,
'category_id' => $categoryMap[$product->category_id] ?? '0',
'title' => $product->title,
'brand_id' => $brandMap[$product->brand_id] ?? 'No brand',
'content1' => $product->content1,
'content2' => $product->content2,
'content3' => $product->content3,
'link_order' => $product->link_order,
'img' => $product->img ?? 'no-image.png',
'in_stock' => $product->in_stock ? 1 : 0,
'is_popular' => $product->is_popular ? 1 : 0,
])->execute();
}
}
}
$finish = time();
$res = $finish - $start . "sec. ";
if ($return) {
echo $res;
Answer::success();
}
}
我将 save() 更改为 insert() - 速度提高了。现在所有 JSON(1107 行)都在 40 秒内导入。
有没有更快的方法将现成的数据从 JSON 加载到数据库中?
如果有 10 万行或一百万行呢?等几个小时是正常的做法吗?
public function importProductFile($file, $return = true)
{
$products = json_decode($file);
$dubTableName = Product::tableName() . "_dub";
$start = time();
if ($this->db->createDuplicateTable(Product::tableName(), $dubTableName)) {
$start = time();
$categoryMap = Category_dub::find()->select(['id', 'id_1c_category'])->indexBy('id_1c_category')->column();
$brandMap = Brands_dub::find()->select(['id', 'id_1c_brand'])->indexBy('id_1c_brand')->column();
foreach ($products as $product) {
Yii::$app->db->createCommand()->insert('product_dub', [
'id_1c_product' => $product->id,
'category_id' => $categoryMap[$product->category_id] ?? '0',
'title' => $product->title,
'brand_id' => $brandMap[$product->brand_id] ?? 'No brand',
'content1' => $product->content1,
'content2' => $product->content2,
'content3' => $product->content3,
'link_order' => $product->link_order,
'img' => $product->img ?? 'no-image.png',
'in_stock' => $product->in_stock ? 1 : 0,
'is_popular' => $product->is_popular ? 1 : 0,
])->execute();
}
}
}
$finish = time();
$res = $finish - $start . "sec. ";
if ($return) {
echo $res;
Answer::success();
}
}
您可以使用this answer and Yii2 docs中提到的批量插入。使用此批量插入,您需要记住事件不会被触发。
Yii::$app->db->createCommand()->batchInsert('product_dub', array_keys(reset($products)), $products)->execute();
我正在尝试将数据从 JSON 文件导入到 MySQL。
public function importProductFile($file, $return = true)
{
$products = json_decode($file);
$dubTableName = Product::tableName() . "_dub";
$start = time();
if ($this->db->createDuplicateTable(Product::tableName(), $dubTableName)) {
$i = 0;
foreach ($products as $product) {
$i++;
$item = new Product_dub();
$item->id_1c_product = $product->id;
$category = Category_dub::findOne(['id_1c_category' => $product->category_id]);
if (!$category) {
Answer::failure("В этом товаре отсутствует категория или такой категории не существует: " . $product->title);
}
$item->category_id = $category->id;
$item->title = $product->title;
$brand = Brands_dub::findOne(['id_1c_brand' => $product->brand_id]);
if (!$brand) {
Answer::failure("В этом товаре отсутствует бренд/изготовитель: " . $product->title);
}
$item->brand_id = $brand->id;
// $item->shortdesc = $product->shortdesc;
$item->content1 = $product->content1;
$item->content2 = $product->content2;
$item->content3 = $product->content3;
$item->link_order = $product->link_order;
$item->img = $product->img;
$item->in_stock = $product->in_stock ? 1 : 0;
$item->is_popular = $product->is_popular ? 1 : 0;
if (!$item->save()) {
Answer::failure("Не удалось импортировать: Проверьте данные в " . $product->title);
}
if ($i == 200) {
break;
}
}
}
$finish = time();
$res = $finish - $start . "sec. ";
if ($return) {
echo $res;
Answer::success();
}
}
我的 JSON 文件中大约有 1100 个对象。将 100 行添加到数据库需要 7 秒。添加 200 行 - 15 秒。 300 = 33 秒,400 = 58 秒。为什么它会随着时间的推移变慢以及如何加快这个过程?
我在本地 OpenServer 服务器上做所有事情。 PHP 7.2 版本,至强 2620v3 处理器,16 GB DDR4,硬盘。
UPD 1.
“您能否尝试不导入并仅确定阅读速度”- 我评论 $item->save()
并获得所有 JSON 文件的 1-2 秒。 “在你的循环的每次迭代中,你都是 运行 2 个数据库查询来加载类别和品牌。” - 我试图删除这些行以进行测试 - 但结果比使用 2 个数据库查询快 1-2 秒。
UPD 2.
我将 save()
更改为 insert()
- 速度提高了。现在所有 JSON(1107 行)都在 40 秒内导入。
是否有更快的方法将 JSON 中的现成数据加载到数据库中? 如果有 10 万行或一百万行呢?等几个小时是正常的做法吗?
public function importProductFile($file, $return = true)
{
$products = json_decode($file);
$dubTableName = Product::tableName() . "_dub";
$start = time();
if ($this->db->createDuplicateTable(Product::tableName(), $dubTableName)) {
$start = time();
$categoryMap = Category_dub::find()->select(['id', 'id_1c_category'])->indexBy('id_1c_category')->column();
$brandMap = Brands_dub::find()->select(['id', 'id_1c_brand'])->indexBy('id_1c_brand')->column();
foreach ($products as $product) {
Yii::$app->db->createCommand()->insert('product_dub', [
'id_1c_product' => $product->id,
'category_id' => $categoryMap[$product->category_id] ?? '0',
'title' => $product->title,
'brand_id' => $brandMap[$product->brand_id] ?? 'No brand',
'content1' => $product->content1,
'content2' => $product->content2,
'content3' => $product->content3,
'link_order' => $product->link_order,
'img' => $product->img ?? 'no-image.png',
'in_stock' => $product->in_stock ? 1 : 0,
'is_popular' => $product->is_popular ? 1 : 0,
])->execute();
}
}
}
$finish = time();
$res = $finish - $start . "sec. ";
if ($return) {
echo $res;
Answer::success();
}
}
我将 save() 更改为 insert() - 速度提高了。现在所有 JSON(1107 行)都在 40 秒内导入。 有没有更快的方法将现成的数据从 JSON 加载到数据库中? 如果有 10 万行或一百万行呢?等几个小时是正常的做法吗?
public function importProductFile($file, $return = true)
{
$products = json_decode($file);
$dubTableName = Product::tableName() . "_dub";
$start = time();
if ($this->db->createDuplicateTable(Product::tableName(), $dubTableName)) {
$start = time();
$categoryMap = Category_dub::find()->select(['id', 'id_1c_category'])->indexBy('id_1c_category')->column();
$brandMap = Brands_dub::find()->select(['id', 'id_1c_brand'])->indexBy('id_1c_brand')->column();
foreach ($products as $product) {
Yii::$app->db->createCommand()->insert('product_dub', [
'id_1c_product' => $product->id,
'category_id' => $categoryMap[$product->category_id] ?? '0',
'title' => $product->title,
'brand_id' => $brandMap[$product->brand_id] ?? 'No brand',
'content1' => $product->content1,
'content2' => $product->content2,
'content3' => $product->content3,
'link_order' => $product->link_order,
'img' => $product->img ?? 'no-image.png',
'in_stock' => $product->in_stock ? 1 : 0,
'is_popular' => $product->is_popular ? 1 : 0,
])->execute();
}
}
}
$finish = time();
$res = $finish - $start . "sec. ";
if ($return) {
echo $res;
Answer::success();
}
}
您可以使用this answer and Yii2 docs中提到的批量插入。使用此批量插入,您需要记住事件不会被触发。
Yii::$app->db->createCommand()->batchInsert('product_dub', array_keys(reset($products)), $products)->execute();