这次操作,起因是需要获取用户来源及用户性别,而用户的性别信息在第三方授权的中有,存为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. 【系列】 2-SAT

    bzoj 1997 Planar 题目大意: 给一个存在曼哈顿回路的无向图,求该图是否为平面图 思路: 先把曼哈顿回路提出来,则剩下的边的两个端点若有$ABAB$的形式则这两条边必定一个在环外一个在环 ...

  2. macbook pro 一些操作经验记录

    [一]启用root用户 (1)打开终端 (2)输入命令:sudo passwd root (3)给root设置密码 (4)然后再终端输入命令:su root 进行登陆 [二]解压eclipse压缩包, ...

  3. Park Visit(树的直径)

    传送门 Park Visit Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  4. .NETFramework:Stopwatch

    ylbtech-.NETFramework:Stopwatch 1.返回顶部 1. #region 程序集 System, Version=4.0.0.0, Culture=neutral, Publ ...

  5. 网络爬虫之requests模块的使用+Github自动登入认证

    本篇博客将带领大家梳理爬虫中的requests模块,并结合Github的自动登入验证具体讲解requests模块的参数. 一.引入:   我们先来看如下的例子,初步体验下requests模块的使用: ...

  6. 问题 3: 糖果数(candy)

    问题 3: 糖果数(candy) 题目描述 学校准备去春游,委托小明分发糖果,每位同学一袋,数量随机. 一共有N袋糖果,编号为1到N,小明拿了从编号a袋到编号b袋的糖果去分发,小明想知道,他一共拿了多 ...

  7. Apache-kylin-2.0.0-bin-hbase1x.tar.gz的下载与安装(图文详解)

    首先,对于Apache Kylin的安装,我有话要说. 由于Apache Kylin本身只是一个Server,所以安装部署还是比较简单的.但是它的前提要求是Hadoop.Hive.HBase必须已经安 ...

  8. python之迷宫BFS

    # @File: maze_queue_bfs from collections import deque maze = [ [1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 0 ...

  9. Hdu 4778 Gems Fight! (状态压缩 + DP)

    题目链接: Hdu 4778 Gems Fight! 题目描述: 就是有G种颜色,B个背包,每个背包有n个宝石,颜色分别为c1,c2............两个人轮流取背包放到公共容器里面,容器里面有 ...

  10. Educational Codeforces Round 46 (Rated for Div. 2) B. Light It Up

    Bryce1010模板 http://codeforces.com/problemset/problem/1000/B 思路:先用两个数组sumon[]和sumoff[]将亮着的灯和灭的灯累计一下. ...