我正在 MySQL 服务器上测试性能,并用超过2亿条记录填充表。存储过程生成大的SQL字符串非常慢。任何帮助或评论都非常欢迎。
系统信息:
存储过程使用所有要插入表中的值创建一个INSERT sql查询。
DELIMITER $$
USE `test`$$
DROP PROCEDURE IF EXISTS `inputRowsNoRandom`$$
CREATE DEFINER=`root`@`localhost` PROCEDURE `inputRowsNoRandom`(IN NumRows BIGINT)
BEGIN
/* BUILD INSERT SENTENCE WITH A LOS OF ROWS TO INSERT */
DECLARE i BIGINT;
DECLARE nMax BIGINT;
DECLARE squery LONGTEXT;
DECLARE svalues LONGTEXT;
SET i = 1;
SET nMax = NumRows + 1;
SET squery = 'INSERT INTO `entity_versionable` (fk_entity, str1, str2, bool1, double1, DATE) VALUES ';
SET svalues = '("1", "a1", 100, 1, 500000, "2013-06-14 12:40:45"),';
WHILE i < nMax DO
SET squery = CONCAT(squery, svalues);
SET i = i + 1;
END WHILE;
/*SELECT squery;*/
SET squery = LEFT(squery, CHAR_LENGTH(squery) - 1);
SET squery = CONCAT(squery, ";");
SELECT squery;
/* EXECUTE INSERT SENTENCE */
/*START TRANSACTION;*/
/*PREPARE stmt FROM squery;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
*/
/*COMMIT;*/
END$$
DELIMITER ;
结果:
CALL test.inputRowsNoRandom(20000);
CALL test.inputRowsNoRandom(100000);
结果(按持续时间排序)-陈述时间(总和),以秒为单位||
释放项的 百分比 0.00005
50.00000起始0.00002 20.00000
执行0.00001 10.00000
init 0.00001 10.00000
清理0.00001 10.00000
总计0.00010 100.00000
由于执行查询
变量值说明而
导致的 状态变量的变化 Bytes_received从客户端发送到服务器的21个字节Bytes_sent从服务器
发送的97个字节到客户端
Com_select 1已执行的SELECT语句
数问题1服务器执行的语句数
测试:
我已经从12到64个线程不同的MySQL配置测试,和关闭设置高速缓存,移动日志到另一个硬件磁盘…
使用文本,INT ..还测试
其它信息:
问题:
SELECT squery;
为NULL字符串。发生了什么?(错误一定存在,但我看不到)。mysql -u mysqluser -p数据库名称<数字.sql
更新:
不要在RDBMS中特别使用这种规模的循环。
尝试使用查询快速填充1m行的表
INSERT INTO `entity_versionable` (fk_entity, str1, str2, bool1, double1, date)
SELECT 1, 'a1', 100, 1, 500000, '2013-06-14 12:40:45'
FROM
(
select a.N + b.N * 10 + c.N * 100 + d.N * 1000 + e.N * 10000 + f.N * 100000 + 1 N
from (select 0 as N union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) a
, (select 0 as N union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) b
, (select 0 as N union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) c
, (select 0 as N union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) d
, (select 0 as N union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) e
, (select 0 as N union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) f
) t
我的机器(MacBook Pro 16GB RAM,2.6Ghz Intel Core i7)花了大约8秒的时间才能完成
查询正常,受影响的1000000行(7.63秒)
记录:1000000重复项:0警告:0
UPDATE1 现在使用预备语句的存储过程版本
DELIMITER $$
CREATE PROCEDURE `inputRowsNoRandom`(IN NumRows INT)
BEGIN
DECLARE i INT DEFAULT 0;
PREPARE stmt
FROM 'INSERT INTO `entity_versionable` (fk_entity, str1, str2, bool1, double1, date)
VALUES(?, ?, ?, ?, ?, ?)';
SET @v1 = 1, @v2 = 'a1', @v3 = 100, @v4 = 1, @v5 = 500000, @v6 = '2013-06-14 12:40:45';
WHILE i < NumRows DO
EXECUTE stmt USING @v1, @v2, @v3, @v4, @v5, @v6;
SET i = i + 1;
END WHILE;
DEALLOCATE PREPARE stmt;
END$$
DELIMITER ;
在约3分钟内完成:
mysql> CALL inputRowsNoRandom(1000000);
查询正常,受影响的0行(2分钟51.57秒)
感觉差异8秒vs 3分钟
UPDATE2 为了加快速度,我们可以显式使用事务并批量提交插入。因此,这里是SP的改进版本。
DELIMITER $$
CREATE PROCEDURE inputRowsNoRandom1(IN NumRows BIGINT, IN BatchSize INT)
BEGIN
DECLARE i INT DEFAULT 0;
PREPARE stmt
FROM 'INSERT INTO `entity_versionable` (fk_entity, str1, str2, bool1, double1, date)
VALUES(?, ?, ?, ?, ?, ?)';
SET @v1 = 1, @v2 = 'a1', @v3 = 100, @v4 = 1, @v5 = 500000, @v6 = '2013-06-14 12:40:45';
START TRANSACTION;
WHILE i < NumRows DO
EXECUTE stmt USING @v1, @v2, @v3, @v4, @v5, @v6;
SET i = i + 1;
IF i % BatchSize = 0 THEN
COMMIT;
START TRANSACTION;
END IF;
END WHILE;
COMMIT;
DEALLOCATE PREPARE stmt;
END$$
DELIMITER ;
不同批次大小的结果:
mysql> CALL inputRowsNoRandom1(1000000,1000);
查询正常,受影响的0行(27.25秒)
mysql> CALL inputRowsNoRandom1(1000000,10000);
查询正常,受影响的0行(26.76秒)
mysql> CALL inputRowsNoRandom1(1000000,100000);
查询正常,受影响的0行(26.43秒)
您自己会看到差异 。仍然比交叉联接差3倍以上。
问题内容: 我在任何地方都找不到此答案,但是可以从MySQL中的另一个存储过程调用存储过程吗?我想找回标识值,并在父存储过程中使用它。我们不能再使用FUNCTIONS! 问题答案: 参数应该可以帮助您将值返回给调用过程。基于此,解决方案必须是这样的。
问题内容: 我有一个Winforms应用程序和一个employeeListBox,departmentComboBox和一些文本框来显示员工信息,例如fNameTextbox,lNameTextBox ..... 我想通过departmentCombobox选定的值填充employeelistBox,并从employeeListBox中填充文本框。我具有用于选择部门员工的此存储过程 并填充列表框我
我们前面所学习的 MySQL 语句都是针对一个表或几个表的单条 SQL 语句,但是在数据库的实际操作中,经常会有需要多条 SQL 语句处理多个表才能完成的操作。 例如,为了确认学生能否毕业,需要同时查询学生档案表、成绩表和综合表,此时就需要使用多条 SQL 语句来针对这几个数据表完成处理要求。 存储过程是一组为了完成特定功能的 SQL 语句集合。使用存储过程的目的是将常用或复杂的工作预先用 SQL
问题内容: 这个问题已经在这里有了答案 : 在SQL Server中存储IP地址的数据类型 (10个答案) 3年前关闭。 在MySQL中存储和检索IP地址的最有效方法是什么?现在我正在做: 其中ip是一个字段。 有一个更好的方法吗? 问题答案: 对于IPv4地址,您可能需要将其存储为,并使用和函数从其数字值返回IP地址,反之亦然。 例:
问题内容: 我的存储过程的基本结构是 MySQL版本: 5.1.61-0ubuntu0.11.10.1-log 当前,如果“查询2”失败,则提交“查询1”的结果。 如果任何查询失败,如何回滚事务? 问题答案: 看看http://dev.mysql.com/doc/refman/5.0/en/declare- handler.html 基本上,您声明错误处理程序,它将调用回滚
如果不能理解我的英语是因为我的英语不好。。。。我会尽力解释我的问题。 我试图在mysql(phpmyadmin)中创建一个存储过程,但出现了以下错误: #1064年的今天,您的SQL语法出现错误;请查看与MySQL服务器版本对应的手册,以获取第3行“”附近使用的正确语法 这是存储过程的代码: 这是表格用户的代码: 对不起,我的英语不好