zoukankan      html  css  js  c++  java
  • Mysql

    因为项目原因, mysql用了两年了, 但是一直都未曾去总结过. 最近也是领导让总结项目, 才想起把mysql的使用小结一下.

    一、 Create

    1. 单条插入, sql格式: insert into (列名) values(列值);

    INSERT INTO test.tch_teacher (  Sex, BId, NO, NAME, IsDoublePosition, CreateDate )
    VALUES (  1, '123123123', '123123123', 'Insert', 0, NOW() );

    对于自增的 Id, 是不需要写的, 数据库会自动生成, 但是如果一不小心写上去了, 只要你的Id值, 在数据库中不存在, 是可以插入进去的.

    在mysql中, 就算你插入的 id 为负数, 也是可以插入成功的. 如果数据库中已存在你想插入的 id 值, 则会直接报错.

    2. 多条插入, sql格式: insert into (列名) values(列值),(列值),(列值);

    INSERT INTO test.tch_teacher (  Sex, BId, NO, NAME, IsDoublePosition, CreateDate ) 
    VALUES 
    ( 2, '123123123', '123123123', 'Insert', 0, NOW() ),
    ( 3, '123123123', '123123123', 'Insert', 0, NOW() ),
    ( 4, '123123123', '123123123', 'Insert', 0, NOW() );

    新增多条的时候, 也可以循环调用单条插入语句去插入, 不过, 这种方式并不推荐使用, 因为, 这种方式, 消费更多性能和时间.

    3. 表插入

    可以新建一张临时表: tch_teacher_temp

    CREATE TABLE `tch_teacher_temp` (
      `Sex` smallint(6) DEFAULT NULL,
      `BId` varchar(36) CHARACTER SET utf8 DEFAULT NULL,
      `No` varchar(20) CHARACTER SET utf8 DEFAULT NULL,
      `Name` varchar(30) CHARACTER SET utf8 DEFAULT NULL,
      `IsDoublePosition` bit(1) DEFAULT NULL,
      `CreateDate` datetime DEFAULT NULL,
      PRIMARY KEY (`Id`)
    ) 

    这里有一个取巧的方式, 来获取建表sql

    show create table tch_teacher;

    然后修改一下表名,删除主键(也可不删)就可以了.

    insert into tch_teacher (Sex, BId, NO, NAME, IsDoublePosition, CreateDate) 
    select * from tch_teacher_temp;
    -- 或者
    insert into tch_teacher (Sex, BId, NO, NAME, IsDoublePosition, CreateDate) 
    select Sex, BId, NO, NAME, IsDoublePosition, CreateDate from tch_teacher_temp;

    4. 性能比较

    我粗略测试了一下, 十万级和百万级的数据量, 插入1000条数据. tch_teacher表, 我建了三个索引:Sex, BId, IsDoublePosition

    1). 不使用事务, 一条一条插入, 循环以下这条语句, 1000次

    for (int i = 0; i < 1000; i++)
    {
        var param = new { BId = Guid.NewGuid(), Name = names[ran.Next(9)] + names[ran.Next(9)] + i, IsDoublePosition = i % 2, CreateDate = DateTime.Now, Sex = i % 2, No = ran.Next(100000, 9999999) };
        conn.Execute(insertSql, param);
    }

     

    2). 在使用事务的情况下,  还是循环这条语句, 不同的是, 在循环结束处, 加入事务提交(这次的插入是在上次的数据量基础上, 也就是说, 这次插入前, 数据比上次多1000条)

    var tran = conn.BeginTransaction();
    for (int i = 0; i < 1000; i++)
    {
        var param = new { BId = Guid.NewGuid(), Name = names[ran.Next(9)] + names[ran.Next(9)] + i, IsDoublePosition = i % 2, CreateDate = DateTime.Now, Sex = i % 2, No = ran.Next(100000, 9999999) };
        conn.Execute(insertSql, param, tran);
    }
    tran.Commit();

     

    3). 拼接sql语句的情况下, 由于是"(),(),();"格式的, 所以参数我全做入sql中了, 这里参数化的方式, 不好做. (这次的插入也是在上次的数据量基础上, 也就是说, 这次插入前, 数据比上次多1000条)

    StringBuilder sb = new StringBuilder("insert into tch_teacher(BId,Sex,No, Name, IsDoublePosition, CreateDate) values ", 10000);
    for (int i = 0; i < 1000; i++)
    {
        sb.Append(string.Format("('{0}', {1}, '{2}', '{3}', {4}, '{5}'),",
            Guid.NewGuid(),
                i % 2,
                ran.Next(100000, 9999999),
            names[ran.Next(9)] + names[ran.Next(9)] + i,
            i % 2,
            DateTime.Now.ToString("yyyy-MM-dd")));
    }
    sb.Remove(sb.Length - 1, 1);
    conn.Execute(sb.ToString());

    这种方式, 有两个不好的地方, 一个是不能参数化, 另一个是如果插入数据较多, 会导致sql语句太长, 所以并不推荐

    4). 建临时表的方式, 这里我是事先吧临时表建好的, 在代码里面就没有建了

    var insertSql = @"insert into tch_teacher_temp(BId,Sex,No, Name, IsDoublePosition, CreateDate) values(@BId, @Sex, @No, @Name, @IsDoublePosition, @CreateDate);";
    var tran = conn.BeginTransaction();
    for (int i = 0; i < 1000; i++)
    {
        var param = new { BId = Guid.NewGuid(), Name = names[ran.Next(9)] + names[ran.Next(9)] + i, IsDoublePosition = i % 2, CreateDate = DateTime.Now, Sex = i % 2, No = ran.Next(100000, 9999999) };
        conn.Execute(insertSql, param, tran);
    }
    conn.Execute(@"insert into tch_teacher (Sex, BId, NO, NAME, IsDoublePosition, CreateDate) select Sex, BId, NO, NAME, IsDoublePosition, CreateDate from tch_teacher_temp;", null, tran1);
    tran.Commit();

    这种方式, 每次都要新建表, 删除表. 也是挺麻烦的, 这里的测试, 就没有包含新建表和删除表了

    结果:

      十万(ms)  百万(ms)
    sql拼接 230 359
    事务提交 412 511
    临时表 661 1424
    一条一条 27606 36620

    除了一条一条提交方式, 其他的在时间上, 还是能接受的, 但是推荐使用第2种, 事务提交方式, 易用, 清晰, 省事.

    二、Delete

    删除就相对简单多了. 删除sql的格式: delete from 表名 where 条件

    删除的时候, 如果不加where条件, 就是删除整张表的数据, 相当于 where 1=1 ;

    delete from tch_teacher where id=1;

    这是一条最简单的语句了.

    删除的时候, 对于主键的自增没有影响. 比如主键为 1,2,3

    这时候删除了3, 再插入一条数据, 主键为从4开始.

    如果想要让主键又从1开始的话, 需要使用truncate

    truncate table tch_teacher ;

    这样, 表回归初始状态.

    有时候, 通过where查找后, 能得出很多条数据, 但是我只想删除其中的前几条, 那怎么办呢. 有办法

    delete from tch_teacher where isDoublePosition=1 order by id limit 6;

    这条语句, 就是删除 满足条件的, 前6条数据

    三、Update

    sql格式: update 表名  set 列=值 where 条件

    update的where条件也是可以不加的, 不加的情况下, 修改的就是全部数据.

    update tch_teacher set name='黑茶' where id=3;

    修改的时候, 也是可以通过连表的方式, 去修改数据的.

    update  tch_teacher , tch_contact set tch_teacher.`Name`='红茶' where tch_teacher.Id=tch_contact.TId and tch_contact.Id=1003;
  • 相关阅读:
    SpringBoot测试类异常java.lang.Exception: No tests found matching
    Tomcat启动时Creation of SecureRandom instance for session ID很慢
    CentOS7的docker下载后启动失败 Job for docker.service failed because the control process exited with
    Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'img_id'
    阿里云安装MySQL
    阿里云Centos8安装Docker
    如何通过JAVA代码上传图片和视频到阿里云服务器
    使用FDFS上传图片到服务器报错 ERROR server: 39.100.67.73:22122, response status 2 != 0
    生产者消费者模式
    JUC--Lock锁和Condition条件
  • 原文地址:https://www.cnblogs.com/elvinle/p/6213889.html
Copyright © 2011-2022 走看看