【问题标题】:Update/Insert Large table records based on another Table ReferenceID.根据另一个表 ReferenceID 更新/插入大表记录。
【发布时间】:2017-01-30 17:59:31
【问题描述】:

我有一个内部库存系统,其中包含以下 3 个表格

一个。股票 - 从 CSV 文件每日更新。

---------------------------------
| id | MODELNO | Discount | MRP |
---------------------------------
| 1  | MODEL_1 | 40%      | 900 |
| 2  | MODEL_A | 20%      | 600 |
---------------------------------

每天都会截断此表,并从商家的 CSV 文件中导入新的股票数据。(大约 600 万条记录)

b. Cloths Master - 服装大师数据库

----------------------------------------
| ref_id | MODELNO | Name        | MRP |
----------------------------------------
| 80      | MODEL_1 |Some Dress   | 900 |
| 81      | MODEL_A |Another Dress| 600 |
----------------------------------------

MODELNO 是唯一的,ref_id 是主键。此表是内部 Inventory 应用程序的一部分(大约有 450 万条记录)

c。库存表 - 它是内部应用程序的一部分

-------------------------------------------------
| id | ref_id  | Name        | MRP | status      |
-------------------------------------------------
| 1  | 80      |Some Dress   | 900 |   ACTIVE    |
| 2  | 81      |Another Dress| 600 |   INACTIVE  |
--------------------------------------------------

此表存储产品的可用库存,基于库存,如果折扣超过 40%,则产品为ACTIVE,否则默认为INACTIVE

所需的功能是每天我都需要运行一个脚本来循环遍历库存表记录,并且对于 MODELNO 更新库存表中的库存,如果库存表中的记录不存在,那么它需要待补充。

到目前为止,我尝试过的是一个 PHP 脚本。 一个。首先,将 Inventory 表中所有记录的状态设置为 INACTIVE。 湾。并且对于stocks 表中的每条记录,检查MODELNO 是否存在于Cloths Master 表中。 湾。如果记录存在,则获取 ref_id,并检查 ref_id 是否存在于 Inventory Table 中并相应地更新/插入记录。

问题是脚本需要超过 8 小时才能完成。

您能否提出一种有效的方法,可用于实现上述功能。

注意: Inventory 表的所有插入和更新都是使用 CodeIgniter 的批量插入/更新功能完成的。 我将所有状态设置为 INACTIVE,因为 Stock DB 中可能不存在少数产品。

【问题讨论】:

  • 提示:不要存储 '%'。
  • 会这样做,顺便说一句,我已经使用 Mysql Load Inline 将 CSV 文件转储到 DB。还添加了 MODELNO 和 ref_id 字段的索引

标签: php mysql database codeigniter database-trigger


【解决方案1】:

在这种情况下想到的问题是 - 为什么不使用触发器?

创建一个表so_stocks

CREATE TABLE IF NOT EXISTS `so_stocks` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `MODELNO` varchar(50) COLLATE uft8_general_ci NOT NULL DEFAULT '0',
  `Discount` int(10) DEFAULT '0',
  `MRP` int(11) DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=uft8_general_ci;

INSERT INTO `so_stocks` (`id`, `MODELNO`, `Discount`, `MRP`) VALUES
    (1, 'MODEL_1', 40, 900),
    (2, 'MODEL_A', 20, 600);

创建一个表so_inventory

CREATE TABLE `so_inventory` (
    `id` INT(11) NOT NULL AUTO_INCREMENT,
    `ref_id` INT(11) NOT NULL DEFAULT '0',
    `Name` VARCHAR(255) NOT NULL DEFAULT '0' COLLATE 'uft8_general_ci',
    `MRP` INT(11) NOT NULL DEFAULT '0',
    `status` TINYINT(1) NOT NULL DEFAULT '0',
    PRIMARY KEY (`id`)
)
COLLATE='uft8_general_ci'
ENGINE=MyISAM
AUTO_INCREMENT=1
;

最后是一张桌子 so_cloths

CREATE TABLE `so_cloths` (
    `ref_id` INT(11) NOT NULL AUTO_INCREMENT,
    `MODELNO` VARCHAR(50) NOT NULL DEFAULT '0' COLLATE 'uft8_general_ci',
    `Name` VARCHAR(255) NOT NULL DEFAULT '0' COLLATE 'uft8_general_ci',
    `MRP` INT(11) NOT NULL DEFAULT '0',
    PRIMARY KEY (`ref_id`)
)
COLLATE='uft8_general_ci'
ENGINE=MyISAM
AUTO_INCREMENT=1
;

现在是触发器

CREATE DEFINER=`root`@`::1` TRIGGER `so_cloths_after_insert` AFTER INSERT ON `so_cloths` FOR EACH ROW BEGIN
    INSERT INTO so_inventory (ref_id,Name,MRP,status)
    select sc.ref_id,sc.Name, sc.MRP, if (ss.Discount >= 40, 1,0) AS active from so_cloths AS sc
    LEFT JOIN so_stocks AS ss ON (sc.MODELNO = ss.MODELNO)
    WHERE sc.ref_id = new.ref_id;
END

每次您在 so_cloths 中插入一些东西时,都会在 so_inventory 中插入一个。

显然,这取决于您是要在将数据插入 so_stocks 还是 so_cloths 之后再插入数据 - 您必须自己决定 - 但该示例应该会给您一些见解。

触发器语句中的定义器必须更改为您的设置

【讨论】:

  • 谢谢,试一下回来,同时不会触发减慢插入?
  • 当然——但它们肯定比 php 查询快
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-08
  • 2017-08-01
  • 2018-10-08
  • 1970-01-01
相关资源
最近更新 更多