mybatis的collection查询问题以及使用原生解决方案的结果
之前在springboot+mybatis环境的坑和sql语句简化技巧的第2点提到,数据库的一对多查询可以一次查询多级数据,并且把拿到的数据按id聚合,使父级表和子级表都有数据。
但是这种查询,必然要查询大量的重复父数据,如果不用这种方法,而是分级查询,效果会如何?
要知道这2种数据的查询效率如何,用Python可以简单查询到总时长。
首先用pip install MySQL-python这条指令安装,至于出错解决方法就是https://www.cnblogs.com/superxuezhazha/p/6619036.html这篇文章的事了。
上代码:
import MySQLdb
import json
import uuid
import random
import traceback
import time
plan_id = 'assssss'
use_times = 0
def noSubUuid(namespace=None):
global use_times
if namespace == None:
use_times = use_times + 1
return str(uuid.uuid3(uuid.NAMESPACE_DNS,str(use_times))).replace('-','')
else:
return str(uuid.uuid3(uuid.NAMESPACE_DNS,namespace)).replace('-','')
# Add Sample Data.生成示例数据
def addData(cursor, db):
try:
start = 18
user_ids = []
user_number_id = 490
for _ in range(600):
user_id = noSubUuid()
insertUserSql = 'insert into user VALUES (%d,\'%s\',\'%s\',\'YWRtaW4=\',\'%s\',2,0,1,NULL,NULL,NULL,\'2018-08-21 07:20:13\',NULL,NULL,NULL,\'my_ass_bdpf\',\'MXQ2NWRhNDNXNmM0OWQ1dG9rZW5fc2FsdA==\',\'2bbf024395e84adf80e2e72c6330ea57\')'%(user_number_id,user_id,noSubUuid()[20:],noSubUuid())
print(insertUserSql)
cursor.execute(insertUserSql)
user_ids.append(user_id)
user_number_id = user_number_id+1
line_id = 490
man_num_id = 490
study_num_id = 590
limitNum = 450
for _ in range(400):
start = 0
manage_id = noSubUuid()
insertLineSql = 'insert into experiment_teaching_plan_resource_line values (%d,\'%s\',\'%s\',\'%s\')'%(line_id,noSubUuid(),plan_id,manage_id)
print(insertLineSql)
cursor.execute(insertLineSql)
line_id = line_id + 1
insertManaSql = 'insert into resource_management values (%d,\'%s\',\'%s\',\'%s\',\'%s\',\'%s\',\'%s\',\'20180109000000\',\'my_ass_bdpf\',4)'%(man_num_id,noSubUuid(),noSubUuid(),noSubUuid(),manage_id,noSubUuid(),noSubUuid())
print(insertManaSql)
man_num_id = man_num_id + 1
cursor.execute(insertManaSql)
for user_id in user_ids:
if(start >= limitNum):
return
if(random.randint(0, 2) == 1):
insertStudSql = 'insert into course_resource_study values (%d,\'%s\',\'%s\',\'%s\',null,null,null)'%(study_num_id,noSubUuid(),manage_id,noSubUuid())
print(insertStudSql)
cursor.execute(insertStudSql)
study_num_id = study_num_id + 1
start = start + 1
#
db.commit()
except Exception as e:
print(traceback.format_exc())
db.rollback()
# Rollback Sample Data.如果数据量过大对服务器造成影响,可以回滚示例数据
def rollbackData(cursor, db):
try:
cursor.execute('delete from course_resource_study where student_id in (select uid from user where user_col3 = \'my_ass_bdpf\')')
cursor.execute('delete from user where user_col3 = \'my_ass_bdpf\'')
cursor.execute('delete from experiment_teaching_plan_resource_line where resource_management_id in (select rm.resource_management_id COLLATE utf8_general_ci from resource_management rm where experimental_time = \'my_ass_bdpf\')')
cursor.execute('delete from resource_management where experimental_time = \'my_ass_bdpf\'')
db.commit()
except Exception as e:
print(traceback.format_exc())
db.rollback()
# Query data like mybatis collection query.像Mybatis的collection查询一样查询数据
def SelectAtOnce(cursor, db):
sql = 'select etp.*,rm.*,crs.* '\
+ 'from experiment_teaching_plan etp '\
+ 'JOIN experiment_teaching_plan_resource_line etpl ON etp.id=etpl.teaching_plan_id '\
+ 'JOIN resource_management rm ON rm.resource_management_id=etpl.resource_management_id COLLATE utf8_general_ci '\
+ 'JOIN course_resource_study crs ON rm.resource_management_id=crs.resource_management_id '\
+ 'where etp.id=\'assssss\''
cnt = cursor.execute(sql)
# Query data step by step.分级查询数据
def SelectByStep(cursor, db):
cursor.execute('select * from experiment_teaching_plan where id=\'assssss\'')
results = cursor.fetchall()
plan_id = results[0][0]
cursor.execute('select * from experiment_teaching_plan_resource_line where teaching_plan_id=\'%s\''%(plan_id,))
ids = ','.join(list(map(lambda a:"'" + a[3] + "'",cursor.fetchall())))
cursor.execute('select * from resource_management where resource_management_id in (%s)'%ids)
ids = ','.join(list(map(lambda a:"'" + a[4] + "'",cursor.fetchall())))
cursor.execute('select * from course_resource_study where resource_management_id in (%s)'%ids)
#
if __name__ == '__main__':
db = MySQLdb.connect("localhost", "root", "acmicpc", "my_ass_bdpf", charset='utf8')
cursor = db.cursor()
addData(cursor, db)
#rollbackData(cursor, db) start = time.time()
SelectAtOnce(cursor, db)
mid = time.time()
print(mid - start) SelectByStep(cursor, db)
print(time.time() - mid) cursor.close()
db.close()
#
插入、回滚、查询一条龙
mysql代码:
DROP TABLE IF EXISTS `resource_management`;
CREATE TABLE `resource_management` (
`id` int(10) NOT NULL AUTO_INCREMENT COMMENT '自增ID',
`course_structure_id` varchar(255) COLLATE utf8_unicode_ci NOT NULL COMMENT '课程体系ID',
`course_classification_id` varchar(255) COLLATE utf8_unicode_ci NOT NULL COMMENT '课程分类ID',
`course_content_id` varchar(32) COLLATE utf8_unicode_ci NOT NULL COMMENT '课程内容ID',
`resource_management_id` varchar(32) COLLATE utf8_unicode_ci NOT NULL COMMENT '实验主键ID',
`resource_management_name` varchar(100) COLLATE utf8_unicode_ci NOT NULL COMMENT '实验名称',
`resource_management_desc` varchar(200) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '描述',
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`experimental_time` varchar(255) COLLATE utf8_unicode_ci NOT NULL COMMENT '实验时长',
`resource_order` int(255) NOT NULL COMMENT '文档顺序',
PRIMARY KEY (`id`),
UNIQUE KEY `UNIQUE_VIDEONAME` (`resource_management_name`,`course_content_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='实验基本信息表'; #
# Data for table "experiment_teaching_plan"
# INSERT INTO `experiment_teaching_plan` VALUES ('27421b344b7242a980e139dd3c25f11e','5b3fb1014c62492cb2193686bdf90d45','ass','assss','2019-01-10 16:22:27'),('assssss','27adf7cee44347b4847943c1548887c4','my_test','my_test','2019-04-05 11:23:42'),('ferhh','gfjtjtjtr','在哪?','deswrtyuio','0000-00-00 00:00:00'); DROP TABLE IF EXISTS `experiment_teaching_plan_resource_line`;
CREATE TABLE `experiment_teaching_plan_resource_line` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增ID',
`resource_line_id` varchar(32) NOT NULL COMMENT '中间表ID',
`teaching_plan_id` varchar(32) NOT NULL COMMENT '课程教学计划表主键ID',
`resource_management_id` varchar(32) NOT NULL COMMENT '课程资源表主键ID',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='课程教学计划和资料库关联'; DROP TABLE IF EXISTS `course_resource_study`;
CREATE TABLE `course_resource_study` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`student_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '学生ID',
`resource_management_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '实验ID',
`course_content_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '实验内容ID',
`experiment_summary` longtext COMMENT '实验总结',
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NULL DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='学生实验学习关系表';
写好之后把这段mysql代码在mysql服务器上运行,之后用这段python代码查询。
结果如下:

可以看到,包含大量重复父级数据的查询(这次数据量有80104条)会严重影响查询效率,如果数据量再大一些,或者查询级数再深一些,可能就会彻底堵死整个http请求,使某个客户端得不到回应。
如果考虑到mybatis的collection查询比分级查询快的情况,数据量事实上小得不值一提了(这个例子有80000条数据,稍微有点用的网站储存的数据可能都不止一点)
所以Mybatis的这种collection查询功能不是特别推荐(应该说凡是大数据量的系统都不应该用这种查询),分开查代码会麻烦一些,但是后期数据量上来的话性能占优。
mybatis的collection查询问题以及使用原生解决方案的结果的更多相关文章
- MyBatis使用Collection查询多对多或一对多结果集bug
情况描述:当使用JOIN查询,如果SQL查询出来的记录不是按id列排序的,则生成的List结果会有问题 案例: 1) 数据库模型 简而言之一个Goods包含多个Goods_Img 2) Java Be ...
- mybatis使用collection查询集合属性规则
接上篇mybatis使用associaton进行分步查询 相关的类还是上篇中的类. 查询部门的时候将部门对应的所有员工信息也查询出来 DepartmentMapper.xml <!--嵌套结果集 ...
- Mybatis之关联查询
一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) 1.2.创建表和数据 创建一张教师表和班级表,这里我们假设一个老师只负责教一个班,那么老师和班级之间的关系就是一种一对一的关 ...
- 【转载】Mybatis多参数查询映射
转载地址:http://www.07net01.com/zhishi/402787.html 最近在做一个Mybatis的项目,由于是接触不久,虽然看了一下资料,但在实际开发中还是暴 露了很多问题,其 ...
- MyBatis多对多查询
-------------------siwuxie095 MyBatis 多对多查询 以订单和商品为例,即 一个订单可 ...
- Mybatis之关联查询及动态SQL
前言 实际开发项目中,很少是针对单表操作,基本都会联查多表进行操作,尤其是出一些报表的内容.此时,就可以使用Mybatis的关联查询还有动态SQL.前几篇文章已经介绍过了怎么调用及相关内容,因此这里只 ...
- mybatis 联表查询
一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) 1.2.创建表和数据 创建一张教师表和班级表,这里我们假设一个老师只负责教一个班,那么老师和班级之间的关系就是一种一对一的关 ...
- mybatis组合实体查询
mybatis组合实体查询 <resultMap id="wxIndexMap" type="com.o2o.common.model.wxuntity.WxInd ...
- mybatis的嵌套查询(嵌套查询nested select和嵌套结果nested results查询)区别
(转自:http://blog.csdn.net/canot/article/details/51485955) Mybatis表现关联关系比hibernate简单,没有分那么细致one-to-man ...
随机推荐
- [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed
1.在vs编写时出现这个问题(以下为网络查询结果) 问题的原因是“SSL: CERTIFICATE_VERIFY_FAILED”. Python 升级到 2.7.9 之后引入了一个新特性,当使用url ...
- css学习_css布局案例
1.中间栏先加载 !!!(若不是这个条件的话 ,那可以用 calc 或者flex布局来实现 中间栏自适应,左右栏定宽) 2.中间栏自适应 width:100% 3.左右栏固定宽 左中右 ...
- java--List、Set、Map的基础
好像面试很多面试官都喜欢问这它们的一些问题,所以在这里我稍微总结一下,并把大佬们的文章链接贴在后面. 首先我们借鉴了https://www.cnblogs.com/SnowingYXY/p/67273 ...
- windows创建定时任务执行python脚本
一.创建定时任务 \ [程序或脚本]文本框中填的是Python编译器的名称,一般就是python.exe, [起始于]文本框中填的是Python编译器的目录,上图中假设你的Python编译器的完整路径 ...
- Jackson Annotation Examples
1. Overview In this article, we’ll do a deep dive into Jackson Annotations. We’ll see how to use the ...
- mongodb 参数优化
1.大部分IO操作为随机IO,建议采用SSD或PCIE,普通硬盘RAID10 2.IO调度算法.普通磁盘:deadline避免IO请求出现“饥饿”现象,SSD/PCIE:noop简单的先进先出处理请求 ...
- node.js爬取ajax接口数据
爬取页面数据与爬取接口数据,我还是觉得爬取接口数据更加简单一点,主要爬取一些分页的数据. 爬取步骤: 1.明确目标接口地址,举个例子 : https://www.vcg.com/api/common/ ...
- 2019-04-20 Python之科学计算库学习总结
一.numpy库和matplotlib库的学习 (1)numpy库介绍:科学计算包,支持N维数组运算.处理大型矩阵.成熟的广播函数库.矢量运算.线性代数.傅里叶变换.随机数生成,并可与C++/Fort ...
- urlib库的使用
urlib库实际上不是很常用,因为其api调用复杂,已被requests模块取代. 1.request发送请求 from urllib import request #默认指定的是get请求 #url ...
- 20175211 2018-2019-2 《Java程序设计》第五周学习总结
目录 教材学习内容总结 第六章 接口与实现 教材学习中的问题和解决过程 代码调试中的问题和解决过程 代码托管 上周考试错题总结 学习进度条 参考资料 教材学习内容总结 第六章 接口与实现 6.1 接口 ...