mysql - 加快 MySQL 插入存储过程

标签 mysql bulkinsert

我正在尝试加快从 CSV 文件中插入 1000 条记录的过程。我有一个连接到联系人电话表的联系人表。

这是我的相关 SQL 结构:

Contact Table
+----+-----------+----------+------------------+------------+----------------+
| id | firstName | lastName |     primaryEmail | locationId | organizationId |
+----+-----------+----------+------------------+------------+----------------+
|  1 |      John |      Doe | jdoe@noemail.com |          1 |              1 |
+----+-----------+----------+------------------+------------+----------------+

Contact Phone Table
+----+-----------+--------------+---------+----------------+
| id | contactId |       number | primary | organizationId |
+----+-----------+--------------+---------+----------------+
|  1 |         1 | +15555555555 |       1 |              1 |
+----+-----------+--------------+---------+----------------+
|  2 |         1 | +11231231234 |       0 |              1 |
+----+-----------+--------------+---------+----------------+

如果电话和/或电子邮件尚不存在,我需要使用设置为主要电话的单个电话插入新联系人。 CSV 中的联系人不能有多个电话号码,但可以在添加后手动更新。

这是我想出的MySQL存储过程

DELIMITER $$

CREATE PROCEDURE `save_bulk_contact`(IN last_name VARCHAR(128), IN first_name VARCHAR(128), IN email VARCHAR(320), IN location_id BIGINT, IN organization_id BIGINT, IN phone_number VARCHAR(15))
BEGIN

    DECLARE CheckExists INT;
    DECLARE insert_id BIGINT;

    SELECT COUNT(*) INTO CheckExists FROM contact
    LEFT JOIN contact_phone ON contact.id = contact_phone.contactId
    WHERE contact.organizationId = organization_id 
        AND contact.locationId = location_id
        AND ((`primaryEmail` <> '' AND `primaryEmail` = email) OR `number` = phone_number);

    IF (CheckExists = 0) THEN
        INSERT INTO contact
            (`lastName`, `firstName`, `primaryEmail`, `locationId`, `organizationId`)
        VALUE (last_name, first_name, email, location_id, organization_id);
        SET insert_id = LAST_INSERT_ID();

        INSERT INTO contact_phone
            (`contactId`, `number`, `type`, `primary`, `organizationId`)
        VALUE (insert_id, phone_number, 'CELL', 1, organization_id);
    END IF;

END$$

DELIMITER ;

我将这个存储过程与 Spring JDBC 模板批量更新一起使用。联系人 CSV 可以包含 50,000 多个联系人。我尝试了很多方法来解决这个问题,但没有一个看起来很好。这是另一个尝试:Insert 1000s of records with relationship and ignore duplicates using JDBC & MySQL但我没有收到任何答复。我使用包含 100,000 个联系人的 CSV 文件运行这种 Java 繁重的方法,而我的数据库中已有大约 5000 个联系人,这花了将近 3 个小时。

大约 30 分钟前,我使用上述存储过程从我的 Web 应用程序开始了 50,000 个联系人的 CSV 上传。到目前为止,它已经添加了大约 23,000 个。

我该怎么做才能使这个过程更有效率并更快地完成?

更新:我刚完成 50,000 个插入,用了 1.7 小时。

最佳答案

首先。将索引添加到两个表中的组织 ID 和位置 ID(如果尚未存在)。将您的检查存在分成两个语句以使用内部连接并摆脱“或”

SELECT COUNT(*) INTO CheckExists FROM contact
INNER JOIN contact_phone ON contact.id = 
contact_phone.contactId
WHERE contact.organizationId = organization_id 
    AND contact.locationId = location_id
    AND ((`primaryEmail` <> '' AND `primaryEmail` = email);

SELECT COUNT(*) INTO CheckExistsTwo FROM contact
INNER JOIN contact_phone ON contact.id = 
contact_phone.contactId
WHERE contact.organizationId = organization_id 
    AND contact.locationId = location_id
    AND  `number` = phone_number;

IF (CheckExists = 0 OR CheckExistsTwo = 0)

关于mysql - 加快 MySQL 插入存储过程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50978884/

相关文章:

mysql - 使用ASP和MySQL设置字符集

php - 数据库时间数据检索、基于时间的查询

java - 使用 hibernate native 查询批量插入

csv - Grails域级别的saveAll实现

mysql - 如何配置/设计一个每15分钟插入30,000次的表?

python - 使用 Python 批量插入 vertica

MySql 插入重复键更新 - 唯一

java - 访问 EntityManager 时出错 - openjpa - WAS 自由配置文件

Mysql批量插入不更新LAST_INSERT_ID

javascript - 无法使用 sequelize-auto 读取未定义的属性 'findOrCreate'