【问题标题】:Faster way to do individual inserts?更快的方式来做单独的插入?
【发布时间】:2011-05-04 23:24:45
【问题描述】:

我有一个处理在树中添加节点的存储过程。基本上表结构是

id INT PRIMARY
label VARCHAR(1) /* the value of the node which is a character */
parent_id INT /* id of the parent node */

这是我的存储过程:

/* 
    takes a word, and adds every character in to the table 
    where every character is a child of the previous character
    the first character of every word is a child of the root
*/
CREATE PROCEDURE rule(IN word VARCHAR(255))
BEGIN
    /* (parent_id = 0) => child of root */
    DECLARE pid INT DEFAULT 0; /* parent id */
    DECLARE npid INT DEFAULT 0;
    DECLARE strlength INT;
    DECLARE j INT DEFAULT 1; 
    DECLARE query_count INT DEFAULT 0;
    DECLARE active_char VARCHAR(1);
    SET strlength = LENGTH(word);
    /* loop through the word */
    WHILE j <= strlength DO
        /* get a single character from word */
        SET active_char = SUBSTR(word,j,1);
        /* if the character doesn't already exist, insert it */
        SELECT COUNT(*) INTO query_count FROM tree
        WHERE parent_id = pid AND label = active_char;
        IF (query_count = 0) THEN
            INSERT INTO tree (label, parent_id)
            VALUES (active_char,pid);
        END IF;
        /* Set the new parent id */
        SELECT id INTO npid FROM tree
        WHERE label = active_char AND parent_id = pid;
        SET pid = npid;
        SET j = j + 1;
    END WHILE;
END //

我确信我可以进行一些调整以使程序更有效率,但我想不出任何可以显着减少所需时间的方法。

我正在处理很多单词,这意味着此过程运行了 100,000 次,这反过来意味着大量插入和大量查询。这需要几个小时甚至几天(不确定,因为我放弃了等待并停止了这个过程)。

问题是,我认为我不能进行批量插入,因为每个插入都依赖于前一个插入。

我想知道是否有某种方法可以创建一个存储在主内存中的虚拟表以快速执行所有这些操作,然后将结果保存到实际表中。

目前,我能想到的唯一可能的解决方案是在 PHP 中构建树,然后进行批量插入。我认为这应该更快,但我不确定到什么程度。

任何帮助将不胜感激。

谢谢。

【问题讨论】:

  • 这在数据库之外可能会更快,因为它不需要担心 IO 和一致性。
  • 您要插入的表格是什么样的?任何索引?主键?
  • 该表有 3 个字段。 id、label 和 parent_id,其中 id 为主键。没有索引。
  • 使用 last_insert_id() 应该消除最后一个查询。你为什么要检查一个你没有插入的字符是否已经存在?

标签: mysql sql database stored-procedures


【解决方案1】:

虽然恐怕我不能声称自己使用过它,但将数据作为 XML 传递到存储过程并将其处理为 described here 似乎是一种合理的方法。注: MySQL 5.1 或更高版本。

【讨论】:

  • 理想情况下,xml 将具有树的结构,即子节点将是 xml 中的子元素,然后处理起来会非常快,因为我不必循环遍历 1000 个元素查找和识别。我不认为我可以从数据库中获取这种格式,所以如果我确实使用 xml,我可能会考虑使用它而不是完全使用数据库
【解决方案2】:

一些想法:

  1. “减少时间”意味着您必须向我们展示架构、索引、查询和EXPLAIN(过程中的每个语句)。
  2. 使用 INSERT IGNORE 而不是您现在使用的 SELECT/INSERT 对。
  3. 您不需要SELECT 退出ID - 使用LAST_INSERT_ID()
  4. 为什么选择到 npid 然后复制到 pid 中?只需选择进入 pid。

【讨论】:

  • @1 我不确定我还能提供什么更多信息。 @2 如何使用 INSERT IGNORE 替换 SELECT 语句? @3 是的,这可能是一个更好的主意。谢谢。 @4 当我第一次运行该程序时,我遇到了一个错误,我认为该语句导致了它。我想也许你可以插入一个你也用来查询的变量。我忘记改回来了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-09-28
  • 1970-01-01
  • 1970-01-01
  • 2018-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多