array(2) { ["docs"]=> array(10) { [0]=> array(10) { ["id"]=> string(3) "428" ["text"]=> string(77) "Visual Studio 2017 单独启动MSDN帮助(Microsoft Help Viewer)的方法" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(8) "DonetRen" ["tagsname"]=> string(55) "Visual Studio 2017|MSDN帮助|C#程序|.NET|Help Viewer" ["tagsid"]=> string(23) "[401,402,403,"300",404]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400964" ["_id"]=> string(3) "428" } [1]=> array(10) { ["id"]=> string(3) "427" ["text"]=> string(42) "npm -v;报错 cannot find module "wrapp"" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "zzty" ["tagsname"]=> string(50) "node.js|npm|cannot find module "wrapp“|node" ["tagsid"]=> string(19) "[398,"239",399,400]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400760" ["_id"]=> string(3) "427" } [2]=> array(10) { ["id"]=> string(3) "426" ["text"]=> string(54) "说说css中pt、px、em、rem都扮演了什么角色" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(12) "zhengqiaoyin" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400640" ["_id"]=> string(3) "426" } [3]=> array(10) { ["id"]=> string(3) "425" ["text"]=> string(83) "深入学习JS执行--创建执行上下文(变量对象,作用域链,this)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "Ry-yuan" ["tagsname"]=> string(33) "Javascript|Javascript执行过程" ["tagsid"]=> string(13) "["169","191"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511399901" ["_id"]=> string(3) "425" } [4]=> array(10) { ["id"]=> string(3) "424" ["text"]=> string(30) "C# 排序技术研究与对比" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "vveiliang" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(8) ".Net Dev" ["catesid"]=> string(5) "[199]" ["createtime"]=> string(10) "1511399150" ["_id"]=> string(3) "424" } [5]=> array(10) { ["id"]=> string(3) "423" ["text"]=> string(72) "【算法】小白的算法笔记:快速排序算法的编码和优化" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "penghuwan" ["tagsname"]=> string(6) "算法" ["tagsid"]=> string(7) "["344"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511398109" ["_id"]=> string(3) "423" } [6]=> array(10) { ["id"]=> string(3) "422" ["text"]=> string(64) "JavaScript数据可视化编程学习(二)Flotr2,雷达图" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "chengxs" ["tagsname"]=> string(28) "数据可视化|前端学习" ["tagsid"]=> string(9) "[396,397]" ["catesname"]=> string(18) "前端基本知识" ["catesid"]=> string(5) "[198]" ["createtime"]=> string(10) "1511397800" ["_id"]=> string(3) "422" } [7]=> array(10) { ["id"]=> string(3) "421" ["text"]=> string(36) "C#表达式目录树(Expression)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "wwym" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(4) ".NET" ["catesid"]=> string(7) "["119"]" ["createtime"]=> string(10) "1511397474" ["_id"]=> string(3) "421" } [8]=> array(10) { ["id"]=> string(3) "420" ["text"]=> string(47) "数据结构 队列_队列实例:事件处理" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "idreamo" ["tagsname"]=> string(40) "C语言|数据结构|队列|事件处理" ["tagsid"]=> string(23) "["246","247","248",395]" ["catesname"]=> string(12) "数据结构" ["catesid"]=> string(7) "["133"]" ["createtime"]=> string(10) "1511397279" ["_id"]=> string(3) "420" } [9]=> array(10) { ["id"]=> string(3) "419" ["text"]=> string(47) "久等了,博客园官方Android客户端发布" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(3) "cmt" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511396549" ["_id"]=> string(3) "419" } } ["count"]=> int(200) } 222 mybatis分页插件 - 爱码网

mybatis 分页插件

网上找到的mybatis分页插件实现原理大多是通过拦截原查询sql , 外层增加分页参数 .
如下
String sql = (String) metaStatementHandler.getValue(“delegate.boundSql.sql”);
//构建新的分页sql语句
String limitSql = “select * from (” + sql + “) $_paging_table limit ?,?”;

然后通过count 语句拿到查询的结果总数, 计算有多少页 , count语句通常如下改造
将sql改写成统计记录数的count 语句,这里是mysql的改写语句,将第一次查询结果作为第二次查询的表
String countSql = “select count(*) as total from (” + sql + “) $_paging”;

当原sql比较复杂的时候, 效率比较低.

粗糙的测试几遍在100万数据的时候.

select count() as total from (" + sql + ") 0.9s
select count(
) as total from table where …; 0.3s

在600万数据的时候是
select count() as total from (" + sql + ") 1分钟
select count(
) as total from table where …; 5s
mybatis分页插件
上图中的2条sql ,在600万数据时,多次测试,交换执行先后顺序测试.效率差距保持10倍以上.

如果原sql含有分组函数的时候,效率差距翻倍增大. (工具显示ms 实际是s秒)
mybatis分页插件
交换执行顺序
mybatis分页插件
不懂数据库查询原理,懂一些sql的语法,觉得可以通过改造原sql ,而不是直接增加一层 select count(*) from (原sql). 性能会更好.

直接上代码, 大部分的情况下,可以把原sql改造为一条直接的count 语句. 如果报错,说明不支持,这条sql的count语句就需要自己写.

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class GenMysqlCountUtil {

/** 结果集的子查询 */
public static Pattern subquery = Pattern.compile("\\(\\s*select[^\\)]+\\)[\\s\\w]+,", Pattern.CASE_INSENSITIVE);
/** 结果集最后一个子查询 */
public static Pattern lastSubquery = Pattern.compile("\\(\\s*select[^\\)]+\\)[\\s\\w]+?(?!from)",
		Pattern.CASE_INSENSITIVE);
/** 外层order by */
public static Pattern pOrder = Pattern.compile(
		"order\\s+by(\\s[\\w\\.]+(\\s*asc|\\s*desc)*)?(\\s*,\\s*[\\w\\.]+(\\s*asc|\\s*desc)*)*",
		Pattern.CASE_INSENSITIVE);
/** 外层group by */
public static Pattern pGroup = Pattern.compile("group\\s+by(\\s[\\w\\.]+)?(\\s*,\\s*[\\w\\.]+)*",
		Pattern.CASE_INSENSITIVE);
/** 外层limit */
public static Pattern pLimit = Pattern.compile("limit", Pattern.CASE_INSENSITIVE);
/** sleect from */
public static Pattern pSelectF = Pattern.compile("select[\\s\\S]+?from", Pattern.CASE_INSENSITIVE);
/** count sum avg max min group_concat */
public static Pattern pAggregate = Pattern.compile(
		"max\\s*\\(|min\\s*\\(|count\\s*\\(|sum\\s*\\(|avg\\s*\\(|group_concat\\s*\\(", Pattern.CASE_INSENSITIVE);
/** 外层having */
public static Pattern pHaving = Pattern.compile("having\\s+[\\s\\W]+", Pattern.CASE_INSENSITIVE);

public static String genCountSql(String sql) {
	Matcher m = null;
	// 去掉结果集的子查询
	m = subquery.matcher(sql);
	while (m.find()) {
		sql = m.replaceAll("");
	}
	// 去掉结果集的最后一个子查询
	m = lastSubquery.matcher(sql);
	while (m.find()) {
		sql = m.replaceAll("");
	}

	int start = -1, end = -1;

	// 去掉最外层limit
	m = pLimit.matcher(sql);
	while (m.find()) {
		start = m.start();
		end = m.end();
	}
	if (start > sql.lastIndexOf(")")) {
		sql = sql.substring(0, start);
		start = -1;
		end = -1;
	}

	// 去掉最外层having
	m = pHaving.matcher(sql);
	/*
	 * while (m.find()) { start = m.start(); end = m.end(); } String having
	 * = null; if (start > sql.lastIndexOf("from")) { having =
	 * sql.substring(start, end); sql = sql.substring(0, start);
	 * 
	 * start = -1; end = -1; }
	 */

	// 去掉最外层order by
	m = pOrder.matcher(sql);
	while (m.find()) {
		start = m.start();
		end = m.end();
	}
	if (start > sql.lastIndexOf(")")) {
		sql = sql.substring(0, start) + sql.substring(end, sql.length());
		start = -1;
		end = -1;
	}

	// 处理最外层group 转count (distinct)
	m = pGroup.matcher(sql);
	while (m.find()) {
		start = m.start();
		end = m.end();
	}
	String group = null;
	if (start > sql.lastIndexOf("from")) {
		group = sql.substring(start, end).replaceFirst("([Gg][Rr][Oo][Uu][Pp])\\s+([Bb][Yy])", "distinct");
		sql = sql.substring(0, start) + sql.substring(end, sql.length());
		start = -1;
		end = -1;
	}

	// 获取select - from
	m = pSelectF.matcher(sql);
	if (!m.find()) {
		return null;
	}

	String countSql = "";
	// 外层有group
	if (group != null) {
		// group 多个字段
		if (group.indexOf(",") > 0) {
			countSql = m.replaceFirst("select count(*) from (select " + group + " from ") + ") unique_alias";
			return countSql;
		}
		countSql = m.replaceFirst("select count(" + group + ") from");
		return countSql;
	}
	// 外层无group by

	// 结果集有聚合函数
	if (pAggregate.matcher(m.group()).find()) {
		return "select 1";
	}
	countSql = m.replaceFirst("select count(0) from");
	return countSql;
}

}

完整的分页插件代码还有代码生成工具链接
分页插件: https://download.csdn.net/download/super_sys/11009842
生成工具: https://download.csdn.net/download/super_sys/11009846

相关文章: