这次操作,起因是需要获取用户来源及用户性别,而用户的性别信息在第三方授权的中有,存为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优化操作的更多相关文章

  1. 记一次 mysql 启动没反应

    记一次 mysql 启动没反应 ,重启linux又可以启动 vim /var/log/mysqld.log 2018-02-04 13:22:49 28507 [ERROR] InnoDB: Cann ...

  2. 记一次MySQL表分区操作

    最近一次日常迭代中,业务线需要对一张大表进行联合查询,查询性能可想而知,测试过程中服务接口直接响应超时,导致服务不可用,最后临时对该表进行分区操作,暂时缓解性能问题.由于是第一次操作表分区,姑且记录一 ...

  3. 记一次mysql数据库被勒索(中)

    背景在上一篇文章里面已经提过了. 现在面临的问题是nextcloud没有mysql数据库,用不起来了. 因为文件没丢,一种方法是启动新的mysql数据库,把文件重新提交一次. 为了程序员的面子,没有选 ...

  4. 记一次mysql数据库被勒索(下)

    背景: nextcloud的mysql数据库被黑,删库勒索.参考:记一次mysql数据库被勒索(上) mysql数据库恢复成功,nextcloud还是无法连接.参考:记一次mysql数据库被勒索(中) ...

  5. 记一次mysql事务未提交导致锁未释放的问题

    记一次mysql事务未提交导致锁未释放的问题 ## 查看未提交的事务(3秒内未操作的事务) SELECT p.ID AS conn_id, P.USER AS login_user, P.HOST A ...

  6. 【夯实Mysql基础】记一次mysql语句的优化过程

    1. [事件起因] 今天在做项目的时候,发现提供给客户端的接口时间很慢,达到了2秒多,我第一时间,抓了接口,看了运行的sql,发现就是 2个sql慢,分别占了1秒多. 一个sql是 链接了5个表同时使 ...

  7. 记一次MYSQL更新优化

    引言 今天(August 5, 2015 5:34 PM)在给数据库中一张表的结构做一次调整,添加了几个字段,后面对之前的数据进行刷新,刷新的内容是:对其中的一个已有字段url进行匹配,然后更新新加的 ...

  8. 记一次mysql故障恢复

    事情要从俩月前的一个坑说起,一台新的测试服务器,新项目一元夺宝用的. 配置aws上的一台云主机,系统盘8G,一块300G的云硬盘. 拿到机器后,另一运维小哥安装php,nginx,mysql等软件. ...

  9. 记一次MySql入库后,文本出现乱码的问题

    最近采用ADO.NET开发了一个工具,解析了一条如下的日志并入库(MySql) -- :: [INFO] roleName=♣丶伊诺,orderId=,price= 发现入库后的roleName中的♣ ...

随机推荐

  1. codeforces 690C2 C2. Brain Network (medium)(bfs+树的直径)

    题目链接: C2. Brain Network (medium) time limit per test 2 seconds memory limit per test 256 megabytes i ...

  2. module+standard library.py

    #导入模块 import sys sys.path sys.path.append('D:\program files\Python34\PyWorks') #hello.py文件路径 #不用appe ...

  3. Linux系统的方法论

    Linux系统的方法论 https://www.cnblogs.com/youxia/p/LinuxDesktop001.html 阅读目录 特别说明 什么情况下适合玩Linux桌面 Linux桌面系 ...

  4. bzoj 4987 Tree —— 树形DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4987 其实就是在树上找有 k 个点的连通块(路径上的点都选是最优的),之间的边都走了两遍,只 ...

  5. threesixty.min.js 和jquery.threesixty.js使用总结----实现360度展示

    最近公司做一个项目需要360度展示汽车的外观,就用到了threesixty.min.js,自己总结一下使用方法: treesixty.min.js 源码: /*! threesixty-slider ...

  6. (二十八)分类信息的curd-分类信息删除

    删除分类步骤分析: 1.在list.jsp上编写 删除连接 /store/adminCategory?method=delete&cid=?? 2.在delete方法中 获取cid 调用ser ...

  7. ccflow_005.请假流程-傻瓜表单-审核组件模式

    ccflow_005.请假流程-傻瓜表单-审核组件模式 ' 用审核组件演示各个流程应用 首先设置节点,填写请假单的 表单方案.选择内置傻瓜表单.我们之前创建的表单就回来了. 可以点击下面的设计傻瓜表单 ...

  8. 在 DotNetty 中实现同步请求

    一.背景 DotNetty 本身是一个优秀的网络通讯框架,不过它是基于异步事件驱动来处理另一端的响应,需要在单独的 Handler 去处理相应的返回结果.而在我们的实际使用当中,尤其是 客户端程序 基 ...

  9. poj2385【基础DP】

    挑战DP 题意: 有两棵树,给每分钟有苹果掉落的苹果树,一开始B在 1 树下,B最多只能移动W步,求一个最大数量拿到的. 思路: 一开始想的是,我对于每分钟情况来说无非是等于之前的在本位置+1,或者等 ...

  10. BFS+PRIM

    转载请注明出处:優YoU http://user.qzone.qq.com/289065406/blog/1299324104 在一个y行 x列的迷宫中,有可行走的通路空格' ',不可行走的墙'#', ...