问题背景:
- 有a、b、c三个表,a跟b、c都是一对多的关系,a有自增主键a.id,这是排序分页的依据,但按BOSS要求,不许在b、c表中添加a.id的冗余字段(包括外键手段,外键是使用的a中另一个保证唯一的定长字符串a.guid);
- b、c表中均有字段用于作筛选条件,且由于a跟b、c都是一对多的关系,无法在a表中添加b、c表的筛选用字段作冗余;
- 说是由于预计数据量会非常大(百万级),不允许使用join连接,且由于考虑以后迁移其他数据库的可能性,不允许使用自增主键id做外键,包括不允许使用自增主键id作为其他表的冗余字段。
需求:
- 获取a表数据列表,分页显示,排序依据是a.id;
- 有必选的筛选条件,在a表中,在此举例为a.set;
- 有可选的筛选条件,条件分别在b、c表中,在此举例为b.type,c.name。
探索(此问题未解决,求助各位大佬帮忙):
-
此问题的等价join连接SQL语句如下所示:
SELECT a.id,a.guid,a.col1,a.col2 FROM a INNER JOIN b ON a.guid = b.a_guid INNER JOIN c ON a.guid = c.a_guid WHERE a.set = 'xxx' -- 必选条件 AND b.type = 1 -- 整数,可选筛选条件 AND c.name LIKE '%XXX%' -- 模糊查询,可选筛选条件 GROUP BY a.guid -- 去重 ORDER BY a.id -- 按a.id排序 LIMIT 0,10 -- 分页 ;
- 不允许使用join连接,故思路自然是添加冗余字段,问题背景也说明了a表无法添加b、c表的冗余字段,故在b、c表中都添加了a_set(即a.set)的冗余字段;
-
若不考虑分页,仅根据单独的可选筛选条件自然可以先筛选出a.guid,如根据b.type筛选:
SELECT b.a_guid FROM b WHERE b.a_set = 'xxx' AND b.type = 1 GROUP BY b.a_guid;
- 但这样问题自然在于b表中没有a.id字段可供排序,无法进行分页,分页思路自然是上面的语句查询出b.a_guid的结果集后,在a表中使用IN进行查询,然后按a.id进行排序分页,但此思路又有个问题是本身a、b、c三表的数据量预计就会很大,筛选出的b.a_guid的结果集可能也会非常大,可能会导致SQL语句超出长度限制,即便增加了SQL语句的长度限制或者使用子查询的方法,但IN中的数据量太多的话,不也是会很影响查询效率吗,会不会效率还不如使用JOIN连接?
- 就此,思路卡在此处,实在想不出好的解决方案,在此求助路过的大神帮忙,提供一下解决的思路
不想有冗余字段,那就建个关联表,把a b 表的数据关联起来,想排序就加个a.id,索引建起来。
最好不要用IN,In的效率比较低。很多时候JOIN的效率反而更高的,你用到JOIN了已经涉及到多表了,关系型数据库,干的就是关系,擅长的就是查询;百万级,其实ok的;就是控制一下join的表数,关联越多效率就越低。
根据你的业务来设计数据库,业务体现数据未来可能的增长方向。可以先批量撸数据进去然后测一下sql效率看看。