MySQL 性能不佳 INSERT 或 PHP PDO

Posted

技术标签:

【中文标题】MySQL 性能不佳 INSERT 或 PHP PDO【英文标题】:MySQL Poor performance INSERT or PHP PDO 【发布时间】:2016-03-10 12:42:39 【问题描述】:

通常,当用户访问我的网站时,他平均一次“订阅”大约 50 个事件,我们将其保存在 mapping_table 中,它将许多用户链接到许多事件。 maping_table 有大约 50k 个条目,每天增长数百个。

INSERT映射表中这大约 50 行大约需要 10 到 20 秒,这使我的网站看起来很慢。

我无法弄清楚如何改进以下 php 或 SQL 以降低 INSERT 时间,因为它看起来很基本。

这是SHOW CREATE 声明:

    CREATE TABLE `mapping_table` (
     `user_id` char(21) NOT NULL,
     `event_id` char(21) NOT NULL,
     `update_id` char(10) NOT NULL,
     PRIMARY KEY (`user_id`,`event_id`),
     KEY `event` (`event_id`),
     CONSTRAINT `mapping_table_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users_table` (`user_id`) ON DELETE CASCADE ON UPDATE NO ACTION,
     CONSTRAINT `mapping_table_ibfk_2` FOREIGN KEY (`event_id`) REFERENCES `events_table` (`event_id`) ON DELETE CASCADE ON UPDATE NO ACTION
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1

我的插入部分的 php 脚本:

    $update_id = 'RandomString';
    $conn = new PDO($pdo_serv, $db_user, $db_pwd);
    $stmt = $conn->prepare("INSERT INTO `mapping_table` (`user_id`, `event_id`, `update_id`)
                    VALUES (:uid,:eid,:upd)");

    //GO THROUGH EACH USER SUBSCRIBED EVENTS AND INSERT THEM
    foreach($subscribed_events AS $event) 
        $stmt->bindParam(':uid', $userid);
        $stmt->bindParam(':eid', $event->id);
        $stmt->bindParam(':upd', $update_id);
        $stmt->execute();
    

我愿意接受任何建议。

其他信息:

如果我 microtime 每次插入,我平均每次插入需要 300 毫秒到 1 秒。

我尝试删除UNIQUE KEY,然后是所有FOREIGN KEYS,然后是所有INDEXES,但这些对性能没有任何影响。

【问题讨论】:

尝试批量插入,而不是单个插入查询。 尝试将AUTO_INCREMENT 数字主键添加到关系表中,并尝试在单个事务中处理所有INSERTs。 我现在会尝试批次INSERT,我会告诉你的。我认为 PDO prepare()execute() 在多个连续查询中非常有效,因此我选择了设计。 这里有几个例子***.com/questions/1176352/… 其他问题...不要使用CHAR,除非该列确实是固定长度的。而是使用VARHAR 【参考方案1】:

根据我的问题,我修改了我的 php,如下batch INSERT

$update_id = 'RandomString';
$conn = new PDO($pdo_serv, $db_user, $db_pwd);

$sql = "INSERT INTO `mapping_table` (`user_id`, `event_id`, `update_id`)
                VALUES ";
$values = "";

//GO THROUGH EACH USER SUBSCRIBED EVENTS GENERATE VALUES STRING
foreach($subscribed_events AS $event) 
    $values .= "('".$userid."','".$event->id."','".$update_id."'),"


//Proceed batch insert
$values = rtrim($values, ",");
$sql .= $values;
$stmt = $conn->prepare($sql);
$stmt->execute();

这将我的平均插入时间减少到每行插入不到 10 毫秒(与之前的每行 300 毫秒到 1 秒相比)。没想到差距会这么大。谢谢。

【讨论】:

如果您出于性能原因观看了此问题,但想保持一点安全,请务必致电 $conn->quote($userid) 而不是 $userid。它会稍微减慢整个过程。即使你绝对确定你的数据源,你也不能保证这在 1 个月,1 年,......所以一定要使用它,最终不会花费太多。

以上是关于MySQL 性能不佳 INSERT 或 PHP PDO的主要内容,如果未能解决你的问题,请参考以下文章

SqlDataAdapter 插入性能不佳

MySQL 中的 UNION ALL 性能不佳

PHP/xdebug profiler require_once 性能不佳

MySQL 视图 - 性能不佳

MySQL:连接小到大表的性能不佳

MySQL 大表性能不佳