1. 问题:为什么要实现分表功能
答:因为当表中的一个字段数据量过大时,查询该表时,就会导致查询时间过久、查询性能下降、数据管理困难等问题。
2. 基本介绍
该字段是用于上传excel文件后,通过 EasyExcel 包的方法,对数据进行压缩处理,保存为csv格式的内容,再存入字段中。
示例数据:
数据库中内容:
由于现在我对上传的文件进行了校验,只能上传1MB大小的文件,故字段内容不多,可若后需求需要加大时,该表的该字段就会‘负重前行’,故需要进行分表,才不会影响查询速度。
3. SQL语句
例如:本来查询该字段需要:
select chartData from chart;
先将分表后的表名 插入到 chartData 字段中,根据该 该字段中的表名取查询数据。
select chartData from chart where id = 1685522817543585826;
select * from chart_2376071455;
4. 实现
在 chartMapper.xml 文件中定义方法,传入动态SQL
千万注意:一定要校验动态SQL语句,防止SQL注入
<select id="queryChartData" resultType="String">${queryChartSql}</select>
在 chartMapper 类中定义方法
String queryChartData(String querySql);
另外定义一个TableService 和 它的实现类 TableServiceImpl
/**
* 动态创建表 插入数据
*/
public interface TableService {
public String createTable(HttpServletRequest request);
}
拼接 SQL 语句都主要实现在 TableServiceImpl 实现类中,通过硬凭借SQL,达成在调用方法时,动态创建表和插入数据的能力。
完善点:还没有将SQL校验工具类引入校验SQL语句,需要注意!
/**
* @author 黄大头
* @date 2023年07月31日 22:15
*/
@Service
public class TableServiceImpl implements TableService {
@Resource
private ChartMapper chartMapper;
public String createTable(HttpServletRequest request) {
String headMap = (String) request.getAttribute("data");
//构建边的DDL语句
StringBuilder sb = new StringBuilder();
String newChartName = "chart_" + RandomUtil.randomNumbers(10).toString();
sb.append("CREATE TABLE if not EXISTS ").append(newChartName).append("(");
// sb.append("id INT PRIMARY KEY AUTO_INCREMENT,");
int count = 1;
System.out.println("headMap = " + headMap);
String[] row = headMap.split("\n");
String firstRow = row[0];
String[] split = firstRow.split(",");
int size = split.length;
for (String value : split) {
sb.append(value)
.append(" varchar(256) not null comment")
.append("'")
.append(value)
.append("'");
if (count < size) {
sb.append(",");
}
count++;
}
sb.append(")");
chartMapper.queryChartData(sb.toString());
//insert into chart_6283616203 values ('1','20'),('2','20'),('3','30')
StringBuilder insertSb = new StringBuilder();
insertSb.append("insert into ")
.append(newChartName)
.append(" values ");
for (int i = 1; i < row.length; i++) {
String[] datas = row[i].split(",");
int length = datas.length;
insertSb.append("(");
for (int j = 0; j < length; j++) {
insertSb.append("'")
.append(datas[j])
.append("'");
if (j < length - 1) {
insertSb.append(",");
}
}
insertSb.append(")");
if (i < row.length - 1) {
insertSb.append(",");
}
}
System.out.println("insertSb = " + insertSb);
for (String s : row) {
System.out.println("s = " + s);
}
chartMapper.queryChartData(insertSb.toString());
return newChartName;
}
}
5. 优化
个人认为这种实现方式并不是很优雅(ps:要做一个优雅的程序员)
所以找了很多资料后,发现可以使用技术:ShardingSphere,有兴趣的小伙伴可以自己上官网看看哦。