MySQL中UPDATE语句使用的实例教程

作者:goldensun 时间:2024-01-27 00:10:40 

一、UPDATE常见用法
首先建立测试环境:
 


DROP TABLE IF EXISTS t_test;
CREATE TABLE t_test (
bs bigint(20) NOT NULL auto_increment,
username varchar(20) NOT NULL,
password varchar(20) default NULL,
remark varchar(200) default NULL,
PRIMARY KEY (bs)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=gbk;

INSERT INTO t_test VALUES (1,'lavasoft','123456',NULL);
INSERT INTO t_test VALUES (2,'hello',NULL,NULL);
INSERT INTO t_test VALUES (3,'haha',zz,tt);

 
1、set一个字段
在表t_test中设置第二条记录(bs为2)的password为'***'。


update t_test t
 set t.password = '***'
where t.bs = 2;

 
2、set多个字段
在表t_test中设置第一条记录(bs为1)的password为'*'、remark为'*'。


update t_test t
 set t.password = '*', t.remark = '*'
where t.bs = 1;

 
3、set null值
在表t_test中设置第三条记录(bs为3)的password为null、remark为null。


update t_test t
 set t.password = null, t.remark = null
where t.bs = 3;

 
这个是按照标准语法写的,在不同的数据库系统中,update还有更多的写法,但是标准写法都是支持的。以上三个例子为了说明情况,每次都更新一行。在实际中,可以通过where语句约束来控制更新行数。

二、UPDATE使用中的相关性能问题以及解决方法
UPDATE的功能是更新表中的数据。这的语法和INSERT的第二种用法相似。必须提供表名以及SET表达式,在后面可以加WHERE以限制更新的记录范围。


UPDATE table_anem SET column_name1 = value1, column_name2 = value2,  WHERE ;

如下面的语句将users表中id等于123的记录的age改为24


UPDATE users SET age = 24 WHERE id = 123;

同样,可以使用UPDATE更新多个字段的值


UPDATE users SET age = 24, name = 'Mike' WHERE id = 123;

上面的UPDATE语句通过WHERE指定一个条件,否则,UPDATE将更新表中的所有记录的值
百万级别的数据,对于mysql应该没有问题。

你这个sql的问题是,相当于修改ONE表里面所有记录的AGE信息,而修改的过程是,对于每一条ONE里面的记录,去TWO里面查询,再修改。而且,期间很可能会有锁之类的东西。
首先,这种sql不应该出现在业务逻辑里面,而应该是后台的job里面。
如果一定要这么做,可以试着用相反的方式,如果不一样的记录不是特别多,那就找到ONE表里面AGE记录跟TWO表不一样的记录,再修改, 例如大概象下面(可能语法不太对):


update ONE,TWO
set ONE.AGE=TWO.AGE
where ONE.ID=TWO.ID AND ONE.AGE != TWO.AGE

当我把数据调到了1000W就更新不了了,下面我来分析原因。
实例:需要根据用户日志的ip地址计算出其地理地址
表结构:
用户日志表(200万条记录),其中address是待填充的字段:


CREATE TABLE `tmp_open_ip` (
`email` varchar(60) NOT NULL DEFAULT '',
`address` varchar(50) NOT NULL DEFAULT '',
`ip` int(10) unsigned NOT NULL DEFAULT '0',
KEY `email` (`email`),
KEY `ip` (`ip`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8

另ip地址数据库表(44万条记录)


CREATE TABLE `ip` (
`s` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '开始ip',
`e` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '结束ip',
`a` varchar(50) NOT NULL DEFAULT '',
KEY `s` (`s`),
KEY `e` (`e`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8

需要根据用户日志表 tmp_open_ip 里的 ip字段到ip地址数据库表里查询出对应的地理地址,将地址填充到address字段。
使用如下update语句执行:


UPDATE tmp_open_ip AS u
INNER JOIN ip
ON u.ip BETWEEN ip.s AND ip.e
SET u.address = ip.a

在笔者的电脑上运行了速度非常之慢,执行了一个多小时(4500s)都没有完,也不知道还要多久。
实在看不过去,于是想到使用insert 是否会快一些,于是重新导一张表 tmp_open_log 与tmp_open_log完全一致。
创建一张表 tmp_open_address,是insert的目标表,为了速度更快,没建索引:


CREATE TABLE `tmp_open_address` (
`email` varchar(60) NOT NULL DEFAULT '',
`address` varchar(50) NOT NULL DEFAULT '',
`ip` int(10) unsigned NOT NULL DEFAULT '0'
) ENGINE=MyISAM DEFAULT CHARSET=utf8

执行insert 语句


insert into tmp_open_address (email,address,ip)
select l.email,ip.a,l.ip
from tmp_open_log as l inner join ip on l.ip between ip.s and ip.e ;
/* Affected rows: 2,543,124 Found rows: 0 Warnings: 0 Duration for 3 queries: 16.922 sec. */

不到17s!本来还想去倒杯水、稍事休息一下,结果已经执行完毕。

到本文写完时,前面的update语句已经执行了5000s,结束仍是遥遥无期。
所以,对于大数据量执行update时,可以考虑改用insert 语句实现,可能麻烦一些,但高速带来的收益远大于麻烦!
后记:
直接杀死了update进程,去看看update执行了多少:运行


SELECT * FROM `tmp_open_ip` where address!=''

结果只有 11,373 ,照这个速度,要运行N天....

标签:MySQL,UPDATE
0
投稿

猜你喜欢

  • PHP hebrev()函数用法讲解

    2023-06-03 12:49:32
  • apache+mysql+php+ssl服务器之完全安装攻略

    2023-11-16 07:34:16
  • FSO组件之文件操作(上)

    2010-05-03 11:01:00
  • Python的互斥锁与信号量详解

    2021-12-24 15:29:34
  • 深入分析PHP引用(&)

    2023-11-23 00:42:35
  • Git如何修改已提交的commit注释

    2023-10-04 02:17:54
  • 浅谈Python中的函数(def)及参数传递操作

    2023-01-20 20:13:54
  • python利用proxybroker构建爬虫免费IP代理池的实现

    2021-10-25 21:18:25
  • 对于Python装饰器使用的一些建议

    2022-05-26 09:05:43
  • 详解python中docx库的安装过程

    2023-01-21 18:32:36
  • numpy中的log和ln函数解读

    2023-06-14 22:46:40
  • mysql使用LOAD语句批量录入数据方法

    2010-03-09 16:31:00
  • Python机器学习应用之基于天气数据集的XGBoost分类篇解读

    2023-09-12 05:45:07
  • 使用git上传到码云分支的实现

    2022-04-01 06:05:06
  • Python打包文件夹的方法小结(zip,tar,tar.gz等)

    2022-01-14 17:40:55
  • 玩转Python发短信的实现

    2021-09-17 20:38:54
  • php+mysql开发的最简单在线题库(在线做题系统)完整案例

    2023-08-21 20:03:14
  • 基于python实现银行管理系统

    2023-11-22 01:32:18
  • Javascript调试之console对象——你不知道的一些小技巧

    2023-08-07 19:24:14
  • Python抓取通过Ajax加载数据的示例

    2023-12-09 21:28:38
  • asp之家 网络编程 m.aspxhome.com