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查询功能不是特别推荐(应该说凡是大数据量的系统都不应该用这种查询),分开查代码会麻烦一些,但是后期数据量上来的话性能占优。

  有时间的话,再测试一下Hibernates这种用缓存的系统会使用哪种机制查询。

原文地址:https://www.cnblogs.com/dgutfly/p/10668141.html

时间: 2024-11-05 12:29:30

mybatis的collection查询问题以及使用原生解决方案的结果的相关文章

mybatis使用collection查询集合属性规则

接上篇mybatis使用associaton进行分步查询 相关的类还是上篇中的类. 查询部门的时候将部门对应的所有员工信息也查询出来 DepartmentMapper.xml <!--嵌套结果集的方式,使用collection标签定义关联的集合类型的属性封装规则 --> <resultMap type="com.mybatis.bean.Department" id="MyDept"> <id column="did"

Mybatis Collection查询集合只出现一条数据

Mybatis Collection查询集合只出现一条数据 1.原因 如果两表联查,主表和明细表的主键都是id的话,明细表的多条只能查询出来第一条. 2.解决办法 级联查询的时候,主表和从表有一样的字段名的时候,在mysql上命令查询是没问题的.但在mybatis中主从表需要为相同字段名设置别名.设置了别名就OK了. 例子: 主表Standard, 从表StandEntity,均有名为id的字段 <resultMap id="StandardAndEntityResultMap"

7. MyBatis一对多查询

一: 准备工作 1. 建立数据 CREATE TABLE boss( b_id INT(11) PRIMARY KEY AUTO_INCREMENT NOT NULL, b_name VARCHAR(255) ); CREATE TABLE manager( m_id INT(11) PRIMARY KEY AUTO_INCREMENT NOT NULL, m_name VARCHAR(255) ); INSERT INTO boss(b_name) VALUES('Tom'); INSERT 

Mybatis关联表查询_5

使用Mybatis实现关联查询,分为一对一和一对多两种情况,最后并对ResultMap进行一个简要说明. 创建表和数据 创建教师表,班级表,学生表, 假设一个老师只负责教一个班,那么老师和班级之间的关系是一对一的关系. 假设一个班级有多个学生,那么班级和学生之间的关系是一对多的关系. CREATE TABLE teacher( t_id number(5) PRIMARY KEY, t_name VARCHAR2(20) ); CREATE TABLE class( c_id number(5)

mybatis的嵌套查询(嵌套查询nested select和嵌套结果nested results查询)区别

(转自:http://blog.csdn.net/canot/article/details/51485955) Mybatis表现关联关系比hibernate简单,没有分那么细致one-to-many.many-to-one.one-to-one.而是只有两种association(一).collection(多),表现很简洁.下面通过一个实例,来展示一下Mybatis对于常见的一对多和多对一关系复杂映射是怎样处理的. 以最简单的用户表订单表这个最简单的一对多做示例: 对应的JavaBean:

Mybatis使用之查询详解

Mybatis使用之查询详解 一:简介 此篇主要知识点: 1.sql语句块 2.select标签属性 3.ResultMap 标签配置 4.一对一关联 5.一对多关联 6.多对多关联 7.嵌套查询 二:SQL语句块 2.1 作用 SQL元素可以被用来定义可重用的SQL 代码段,可以包含在其他语句中.比如在项目中常常做的分页查询.分别需要两条SQL语句.一条是查询所有具体记录信息.另一条需要查询记录数.而两条语句的where条件是一样的.这种类似情况就可以使用SQL语句块来简化配置信息. 2.2

【转载】Mybatis多参数查询映射

转载地址:http://www.07net01.com/zhishi/402787.html 最近在做一个Mybatis的项目,由于是接触不久,虽然看了一下资料,但在实际开发中还是暴 露了很多问题,其中最让我头疼的就是selete的parameterType问题,网上这类的帖子虽然有 但是不全,很多情况下很难找到你想要的答案. 为此我对这个问题进行了总结,希望对像我这样的新手有一定的帮助. (一)单个参数 public List<XXBean> getXXBeanList(String xxC

mybatis 联表查询

一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) 1.2.创建表和数据 创建一张教师表和班级表,这里我们假设一个老师只负责教一个班,那么老师和班级之间的关系就是一种一对一的关系. 1 CREATE TABLE teacher( 2 t_id INT PRIMARY KEY AUTO_INCREMENT, 3 t_name VARCHAR(20) 4 ); 5 CREATE TABLE class( 6 c_id INT PRIMARY KEY AUTO_INCREMEN

&lt;MyBatis&gt;入门五 查询的返回值处理

select : 返回对象:  <select  id = " "  resultType= "对象的全类名"  /> List: <select  id = " "  resultType = "list泛型中的值" /> Map: 1.返回一条记录 Map<String,Object>      key -> 字段 value -> 值