前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >把MySql当作列存数据库使用时多条件and查询如何实现?

把MySql当作列存数据库使用时多条件and查询如何实现?

作者头像
吴就业
发布2021-04-01 17:01:31
3.8K0
发布2021-04-01 17:01:31
举报
文章被收录于专栏:Java艺术Java艺术

可能是为了优化查询性能,也可能是做大数据的惯性思维,才会把MySql数据库当分析型数仓去使用吧。

本篇分享的内容是:当我们把MySql当作列存数据库(OLAP分析型数仓)使用时多条件and查询如何实现。

假设某个表有n列,那么把一行记录按列存储后就需要存约n-1行记录。同时,转为列存后每行都需要多出几列标记这一条记录属于哪个“行记录”,以及存储的是“行记录”哪一列的值。

以用户表为例,假设tb_row_user表结构如下。

id

name

sex

age

那么转为列存后创建的表tb_column_user结构如下。

id

user_id

column_name

column_value

现在我们往表tb_row_user里面插入一条记录。

id

name

sex

age

1

就业

26

如果使用列存,则需要往表tb_column_user插入如下3条记录。

id

user_id

column_name

column_value

1

1

name

就业

2

1

sex

3

1

age

26

当然,我们还需要为列user_idcolumn_namecolumn_value分别创建索引。

现在我们需要查询同时满足年龄大于25岁且性别为男的所有用户的id,我们应该怎样写sql?现在条件只有两个,假如条件有5个,10个呢?

下面是笔者首先想到的一种方法:

代码语言:javascript
复制
select user_id,count(id) as cnt 
from tb_column_user where 
(column_name = 'age' and column_value > '25') 
or 
(column_name = 'sex' and column_value = '男')
group by user_id having cnt = 2;

如果把group by去掉,那么sql就是查询条件满足age大于25或者性别是男的用户,即。

代码语言:javascript
复制
select user_id from tb_column_user where 
(column_name = 'age' and column_value > '25') 
or 
(column_name = 'sex' and column_value = '男');

如果一个用户同时满足这两个条件,那么查询结果同个user_id就会有两条记录,否则如果只满足其中一个条件,那么查询结果这个user_id就只会有一条记录。比如:

user_id

1(匹配年龄>25)

1(匹配性别=男)

所以我们按user_id分组统计得到的cnt就是匹配的条件个数,最后通过having就可以筛选出同时满足两个条件(having cnt = 2)的用户的id

这种方法的sql更便于动态拼接,不过使用这个sql有个前提条件,要求tb_row_user表里面的每一行记录的每一列对应到tb_column_user表都只有一行记录(也可以没有)。

最终的SQL的执行计划如下:

由于使用了OR查询,因此Typeindex,即全索引扫描(遍历索引树),因此性能会随着数据量的增加而越来越慢。

另一种方法,使用join查询,sql如下:

代码语言:javascript
复制
select u1.user_id from tb_column_user as u1 inner join (
 select user_id from tb_column_user where column_name = 'sex' and column_value = '男'
) as u2 
where u1.user_id=u2.user_id and u1.column_name = 'age' and u1.column_value > '25';

这条sql的执行计划如下。

如果再加一个条件sql就会看得很头疼了:

代码语言:javascript
复制
select u1.user_id from tb_column_user as u1 inner join (
    select uu1.user_id from tb_column_user uu1 inner join(
        select user_id from tb_column_user where column_name = 'tag' and column_value = '穷'
    )uu2 
    where uu1.user_id=uu2.user_id and uu1.column_name = 'sex' and uu1.column_value = '男'
) as u2 
where u1.user_id=u2.user_id and u1.column_name = 'age' and u1.column_value > '25';

执行计划如下。

可以看出,使用join查询每个查询都能用到索引,并且外层查询扫描的行数总比内层查询扫描的行数少,经过了层层过滤,最终扫描的行数就是最内层的查询语句所扫描的行数。

总结

方法一:优点是sql清晰易读,缺点是性能差;

方法二:优点是性能相对更好,但缺点是条件越多sql看着越难理解。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-03-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java艺术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 总结
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档