Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么是postgresql';s的单insert语句比mysql快?_Mysql_Postgresql - Fatal编程技术网

为什么是postgresql';s的单insert语句比mysql快?

为什么是postgresql';s的单insert语句比mysql快?,mysql,postgresql,Mysql,Postgresql,我想知道为什么postgresql的单个“insert”语句在启用autocommit时比MySQL的语句要快得多?下面的代码与我对它们所做的代码相同 版本: MySQL: 5.6.10 PostgreSQL: PostgreSQL 9.3.2 on x86_64 表定义: MySQL: CREATE TABLE `user` ( `username` char(36) NOT NULL, `password` char(32) NOT NULL, `register_time

我想知道为什么postgresql的单个“insert”语句在启用autocommit时比MySQL的语句要快得多?下面的代码与我对它们所做的代码相同

版本:

MySQL: 5.6.10 
PostgreSQL:  PostgreSQL 9.3.2 on x86_64
表定义:

MySQL:

CREATE TABLE `user` (
  `username` char(36) NOT NULL,
  `password` char(32) NOT NULL,
  `register_time` datetime NOT NULL,
  `mobile_phone` char(11) NOT NULL,
  `is_admin` enum('yes','no') NOT NULL,
  PRIMARY KEY (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
DELIMITER $$

USE `t_girl`$$

DROP PROCEDURE IF EXISTS `sp_insert_user_simple`$$

CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_insert_user_simple`(
IN f_input      INT
)
BEGIN
    DECLARE i      INT DEFAULT 0;
    WHILE i <= f_input
    DO
        INSERT INTO t_girl.user (`username`, `password`, register_time,mobile_phone,is_admin) 
        VALUES (UUID(),MD5(REPLACE(UUID(),'-','')),DATE_SUB(NOW(),INTERVAL CEIL(RAND()*40)  DAY),CEIL(RAND()*10000)+13800000000,IF(TRUNCATE(RAND()*2,0)=1,'yes','no'));
        SET i = i + 1;
    END WHILE;
END$$

DELIMITER ;
PostgreSQL:

CREATE TYPE ytt_enum AS ENUM ('yes','no');
CREATE TABLE ytt."user" (
  "username" char(36) NOT NULL,
  "password" char(32) NOT NULL,
  "register_time" timestamp  NOT NULL,
  "mobile_phone" char(11) NOT NULL,
  "is_admin" ytt_enum NOT NULL,
  PRIMARY KEY ("username")
) ;
CREATE  or replace function sp_insert_user_simple(
IN f_input      INT
) returns void as
$ytt$
    declare i int := 0;
    v_username char(36);
    v_password char(32);
    v_register_time timestamp;
    v_mobile_phone char(11);
    v_is_admin ytt_enum;
BEGIN

    WHILE i < f_input
    loop
        v_username := uuid_generate_v1();
        v_password :=MD5(REPLACE(uuid_generate_v1()::text,'-',''));
        v_register_time := to_timestamp((now() - '1 day'::interval*ceil(random()*40))::text,'yyyy-mm-dd HH24:MI:SS');
        v_mobile_phone :=CEIL(RANDOM()*10000)+13800000000;
        v_is_admin := (case TRUNC(RANDOM()*2) when 1  then 'yes' else'no' end)::ytt_enum;
        INSERT INTO ytt.user (username, password, register_time,mobile_phone,is_admin) 
        VALUES (v_username,v_password,v_register_time,v_mobile_phone,v_is_admin);
        i := i + 1;
    END loop;
END;
$ytt$language plpgsql;
ytt=# select sp_insert_user_simple(10000); 
 sp_insert_user_simple 
-----------------------

(1 row)

Time: 1177.043 ms
存储功能:

MySQL:

CREATE TABLE `user` (
  `username` char(36) NOT NULL,
  `password` char(32) NOT NULL,
  `register_time` datetime NOT NULL,
  `mobile_phone` char(11) NOT NULL,
  `is_admin` enum('yes','no') NOT NULL,
  PRIMARY KEY (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
DELIMITER $$

USE `t_girl`$$

DROP PROCEDURE IF EXISTS `sp_insert_user_simple`$$

CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_insert_user_simple`(
IN f_input      INT
)
BEGIN
    DECLARE i      INT DEFAULT 0;
    WHILE i <= f_input
    DO
        INSERT INTO t_girl.user (`username`, `password`, register_time,mobile_phone,is_admin) 
        VALUES (UUID(),MD5(REPLACE(UUID(),'-','')),DATE_SUB(NOW(),INTERVAL CEIL(RAND()*40)  DAY),CEIL(RAND()*10000)+13800000000,IF(TRUNCATE(RAND()*2,0)=1,'yes','no'));
        SET i = i + 1;
    END WHILE;
END$$

DELIMITER ;
测试结果: MySQL:

PostgreSQL:

CREATE TYPE ytt_enum AS ENUM ('yes','no');
CREATE TABLE ytt."user" (
  "username" char(36) NOT NULL,
  "password" char(32) NOT NULL,
  "register_time" timestamp  NOT NULL,
  "mobile_phone" char(11) NOT NULL,
  "is_admin" ytt_enum NOT NULL,
  PRIMARY KEY ("username")
) ;
CREATE  or replace function sp_insert_user_simple(
IN f_input      INT
) returns void as
$ytt$
    declare i int := 0;
    v_username char(36);
    v_password char(32);
    v_register_time timestamp;
    v_mobile_phone char(11);
    v_is_admin ytt_enum;
BEGIN

    WHILE i < f_input
    loop
        v_username := uuid_generate_v1();
        v_password :=MD5(REPLACE(uuid_generate_v1()::text,'-',''));
        v_register_time := to_timestamp((now() - '1 day'::interval*ceil(random()*40))::text,'yyyy-mm-dd HH24:MI:SS');
        v_mobile_phone :=CEIL(RANDOM()*10000)+13800000000;
        v_is_admin := (case TRUNC(RANDOM()*2) when 1  then 'yes' else'no' end)::ytt_enum;
        INSERT INTO ytt.user (username, password, register_time,mobile_phone,is_admin) 
        VALUES (v_username,v_password,v_register_time,v_mobile_phone,v_is_admin);
        i := i + 1;
    END loop;
END;
$ytt$language plpgsql;
ytt=# select sp_insert_user_simple(10000); 
 sp_insert_user_simple 
-----------------------

(1 row)

Time: 1177.043 ms
上面的测试显示MySQL的运行时间是69.93秒,而PostgreSQL的运行时间只有1.17秒。

任何答复都将不胜感激。谢谢。

我认为这里发生的事情是MySQL的过程可能正在为每个
插入的
进行提交。在PostgreSQL中,整个过程在最后提交;过程不能运行单个事务。(我不完全确定在autocommit=off的情况下,MySQL的过程是否就是这样运行的,但通过快速查看文档可以看出这一点)

无论如何,您都应该使用
INSERT,
INSERT作为单个语句来执行此操作。。。选择

CREATE  or replace function sp_insert_user_simple(
    IN f_input integer
) returns void AS $$
    INSERT INTO ytt.user (username, password, register_time,mobile_phone,is_admin) 
    SELECT
        uuid_generate_v1(),
        MD5(REPLACE(uuid_generate_v1()::text,'-','')),
        to_timestamp((now() - '1 day'::interval*ceil(random()*40))::text,'yyyy-mm-dd HH24:MI:SS'),
        CEIL(RANDOM()*10000)+13800000000,
        case TRUNC(RANDOM()*2) when 1  then 'yes' else'no' end
    FROM generate_series(1,$1);
$$ LANGUAGE sql;
(我假设这是虚拟用户数据生成?)


另外,请使用
char
,不要使用
varchar
char
是一种糟糕的数据类型,应该避免使用。此外,考虑使用<代码>布尔< <代码> > <代码> iSuthAdmin 列。

尝试测试简单插入查询:

INSERT INTO ytt.user (username, password) VALUES ('a', 'b');

并在程序中循环,从而使时间测量更准确。避免使用其他内置函数(如rng和timestamp),因为它们的性能在大样本上可能会有很大差异,当然,除非您首先测试了这些函数。

不相关,但是:(a)您可以在MySQL中打开ANSI模式,然后使用合理的引用;(b)不要使用
char
类型,使用
varchar
<代码>字符
很糟糕。此外,这两个过程都是不必要的,您应该能够将它们编写为单个
insert
语句,而不需要过程。无论如何:我想知道MySQL的autocommit是否在过程中单独提交每个插入(我没有使用MySQL的过程)。PostgreSQL没有,它在最后对整个函数执行一次提交。这很容易解释区别。谢谢,我明白了。我将尝试使用应用程序语言重写测试代码。
char
没有那么糟糕-在MySQL中。谢谢您的回复。我现在了解了postgresql的特殊自动提交功能。