记一次mysql优化操作
这次操作,起因是需要获取用户来源及用户性别,而用户的性别信息在第三方授权的中有,存为JSON格式,
不想用php去解析获取,所以试试mysql操作
如果你有更好的解决方案,请留言告诉我!
情景简化
表结构
记录用户授权信息,有微博、QQ、微信,个人信息存为user_info
- user_platform
- weibo_id,qq_id,weixin_id,user_info,uid,user_platform_id
性别格式
- 微博 【gender】('m' =>男,'f' => 女,'n' => 未知)
- QQ 【gender】 ('男' ,'女' )
- 微信 【sex】(1 =>男,2 => 女)
附加条件
- 数据量近百万行,处理不能太耗时
用户来源
先来个简单的,因为授权账户不是和用户一一对应,所以就是判断相关第三方id不为空则为对应用户来源,没有涉及绑定所以第三方信息实际唯一(表设计不是很合理,这个略过)
SELECT IF((ISNULL(weixin_id) || weixin_id != '', IF((ISNULL(weibo_id) || weibo_id != '', IF((ISNULL(qq_id) || qq_id != '', '手机', 'QQ'), '微博'), '微信') AS user_source, uid
FROM user_platform
WHERE uid != 0
其中 ISNULL(weixin_id) || weixin_id != '' 用来判断null和空字符串两种情况 也可以用 ISNULL(weixin_id) || LENGTH(TRIM(weixin_id)) < 1
性别获取
- 分两类(gender,sex)去截取性别,
- 然后放到临时表中,处理为统一格式的sex(1=>男,2=>女,0=>未知)
- 在用户表中加一列sex并利用临时表更新
字符替换判断
使用mysql函数
- locate
- mid
以微信为例,判断是否包含性别
SELECT locate('sex":', user_info, 50) AS is_sex
FROM user_platform
WHERE user_info != ''
HAVING is_sex != 0
然后截取性别,开始用
SELECT locate('sex":', user_info, 50) AS is_sex, mid(user_info, locate('sex":', user_info, 50) + 5, 1) AS sex
FROM user_platform
WHERE user_info != ''
HAVING is_sex != 0
发现特变慢,而且locate一样的判断执行两次,不如换做一次
SELECT mid(user_info, is_sex + 5, 1) AS sex, uid
FROM user_platform p, (SELECT locate('sex":', user_info, 50) AS is_sex, user_platform_id
FROM user_platform
WHERE user_info != ''
AND uid != 0
HAVING is_sex != 0
) t
WHERE t.user_platform_id = p.user_platform_id
GROUP BY uid
既然判断index,那如果先知道从哪开始判断,那就先获取最小位置,再利用locate第三个参数pos加快查找
SELECT MIN(is_sex)
FROM (SELECT locate('sex":', user_info) AS is_sex
FROM user_platform
WHERE user_info != ''
HAVING is_sex != 0
) t
获取到最小位置为:57,那就 locate('sex":', user_info,55) ,其实可以用57,保险起见小点啦
效率提升,主要时间上 (本地PC测试): 10.17 sec 》》》7.36 sec
然后插入到临时表,mysql不能直接select into,所以先创建表载insert into
CREATE TABLE user_sex (
uid int(11) NOT NULL,
sex char(1) NOT NULL,
PRIMARY KEY (uid)
)ENGINE = InnoDB DEFAULT CHARSET = `utf8`;
INSERT INTO user_sex
(uid, sex)
SELECT uid, sex
FROM (SELECT mid(user_info, is_sex + 5, 1) AS sex, uid
FROM user_platform p, (SELECT locate('sex":', user_info, 55) AS is_sex, user_platform_id
FROM user_platform
WHERE user_info != ''
AND uid != 0
HAVING is_sex != 0
) t
WHERE t.user_platform_id = p.user_platform_id GROUP BY uid
) tmp
微博和QQ的相同处理,只不过判断的是gender
最后需要处理的是sex字段的统一,用replace搞定
UPDATE user_sex
SET sex = replace(sex, '男', 1);
UPDATE user_sex
SET sex = replace(sex, '女', 2);
UPDATE user_sex
SET sex = replace(sex, 'm', 1);
UPDATE user_sex
SET sex = replace(sex, 'f', 2);
UPDATE user_sex
SET sex = replace(sex, '"', 0);
# 最后一个是发现`gender:""`情况
最后的最后,把临时表删了吧
DROP TABLE user_sex
到这里,可优化的部分还是有的,根据业务,还可以加一些判断减少待处理数据,比方说 uid为0:非注册用户 等等
总结一下,除了在添加user表sex列会锁表比较长时间,
最后的用临时表更新和其余查询操作的锁表时间几乎微乎其微,
把统一操作放临时表也可以避免查询操作等待的时间,
优化无非就是做了大化小的工作。
另外备注下 mysql的sql文件注释符"--"错了,需要一个空格,应该是"-- ".
如果想发现更多,请使用mysql slow query log慢查询设置
set GLOBAL long_query_time=1
set GLOBAL log_slow_queries=ON
show variables like '%slow%'
show variables like '%long_query%'
本文链接 : http://blog.newbmiao.com/2015/09/25/remember-once-mysql-optimize-operations.html
记一次mysql优化操作的更多相关文章
- 记一次 mysql 启动没反应
记一次 mysql 启动没反应 ,重启linux又可以启动 vim /var/log/mysqld.log 2018-02-04 13:22:49 28507 [ERROR] InnoDB: Cann ...
- 记一次MySQL表分区操作
最近一次日常迭代中,业务线需要对一张大表进行联合查询,查询性能可想而知,测试过程中服务接口直接响应超时,导致服务不可用,最后临时对该表进行分区操作,暂时缓解性能问题.由于是第一次操作表分区,姑且记录一 ...
- 记一次mysql数据库被勒索(中)
背景在上一篇文章里面已经提过了. 现在面临的问题是nextcloud没有mysql数据库,用不起来了. 因为文件没丢,一种方法是启动新的mysql数据库,把文件重新提交一次. 为了程序员的面子,没有选 ...
- 记一次mysql数据库被勒索(下)
背景: nextcloud的mysql数据库被黑,删库勒索.参考:记一次mysql数据库被勒索(上) mysql数据库恢复成功,nextcloud还是无法连接.参考:记一次mysql数据库被勒索(中) ...
- 记一次mysql事务未提交导致锁未释放的问题
记一次mysql事务未提交导致锁未释放的问题 ## 查看未提交的事务(3秒内未操作的事务) SELECT p.ID AS conn_id, P.USER AS login_user, P.HOST A ...
- 【夯实Mysql基础】记一次mysql语句的优化过程
1. [事件起因] 今天在做项目的时候,发现提供给客户端的接口时间很慢,达到了2秒多,我第一时间,抓了接口,看了运行的sql,发现就是 2个sql慢,分别占了1秒多. 一个sql是 链接了5个表同时使 ...
- 记一次MYSQL更新优化
引言 今天(August 5, 2015 5:34 PM)在给数据库中一张表的结构做一次调整,添加了几个字段,后面对之前的数据进行刷新,刷新的内容是:对其中的一个已有字段url进行匹配,然后更新新加的 ...
- 记一次mysql故障恢复
事情要从俩月前的一个坑说起,一台新的测试服务器,新项目一元夺宝用的. 配置aws上的一台云主机,系统盘8G,一块300G的云硬盘. 拿到机器后,另一运维小哥安装php,nginx,mysql等软件. ...
- 记一次MySql入库后,文本出现乱码的问题
最近采用ADO.NET开发了一个工具,解析了一条如下的日志并入库(MySql) -- :: [INFO] roleName=♣丶伊诺,orderId=,price= 发现入库后的roleName中的♣ ...
随机推荐
- CodeForces546D:Soldier and Number Game(筛区间素数因子个数和)
Two soldiers are playing a game. At the beginning first of them chooses a positive integer n and giv ...
- Linux 系统开机启动项清理
一般情况下,常规用途的 Linux 发行版在开机启动时拉起各种相关服务进程,包括许多你可能无需使用的服务,例如蓝牙bluetooth.Avahi. 调制解调管理器ModemManager.ppp-dn ...
- JAVA 集合JGL
集合 Java提供了四种类型的“集合类”:Vector(矢量).BitSet(位集).Stack(堆栈)以及Hashtable(散列表).与拥有集合功能的其他语言相比,尽管这儿的数量显得相当少,但仍然 ...
- html 样式之style属性的使用
转自:https://www.ggbiji.com/html-style.html html中的style属性是用来改变html元素的样式的,样式是 在html 4 引入的,它是改变 html元素样式 ...
- liist不同遍历优缺点
JAVA中循环删除list中元素的方法总结 印象中循环删除list中的元素使用for循环的方式是有问题的,但是可以使用增强的for循环,然后今天在使用时发现报错了,然后去科普了一下,再然后发现这是一个 ...
- XCode10 swift4.2 适配遇到的坑
以下是2018年10月23日更新 经过大约一个月的时间的适配,项目正式使用XCode10(以下简称为10 or XC10)大部分库都升级为Swift4.2(以下简称为 4.2 or S4.2),下面是 ...
- Get back Typing Break in Ubuntu 12.04 & 11.10(转载)
转自:http://ubuntuguide.net/get-back-typing-break-in-ubuntu-12-04-11-10 Since Ubuntu 11.10 Oneiric, th ...
- 考拉定时任务框架kSchedule
此文已由作者杨凯明授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 1.背景 目前项目中使用的定时任务框架存在下面这些问题 没有统一的定时任务管理平台 目前项目中使用定时任务的 ...
- codforces 1C Ancient Berland Circus(几何)
题意 给出正多边形上三个点的坐标,求正多边形的最小面积 分析 先用三边长求出外接圆半径(海伦公式),再求出三边长对应的角度,再求出三个角度的gcd,最后答案即为\(S*2π/gcd\),S为gcd对应 ...
- iOS 获取类的字符串名称 Swift4
以下实例基于Swift4,且在class, struct, enum中都可用: class Foo { // 实例属性中指定明确的类名来获取名称 var typeName: String { ...