使用Kettle数据迁移添加主键和索引

简介:

Kettle是一款国外开源的etl工具,纯java编写,绿色无需安装,主要用于数据抽取、转换、装载。kettle兼容了市面上几十种数据库,故用kettle来做数据库的迁移视乎是个不错的选择。

kettle的数据抽取主要在于抽取数据,而没有考虑数据库的函数、存储过程、视图、表结构以及索引、约束等等,而这些东西恰恰都是数据迁移需要考虑的事情。当然,如果在不考虑数据库中的函数、存储过程、视图的情况下,使用kettle进行数据的迁移还算是一个可行的方案。

这篇文章主要是讲述在使用kettle进行数据库的迁移的时候如何迁移主键和索引,为什么要迁移主键和索引?异构数据库之间的迁移很难无缝的实现自定义函数、存储过程、视图、表结构、索引、约束以及数据的迁移,所以多数情况下只需要异构数据库之间类型兼容、数据一致就可以了。但是在有些情况下需要对输出表进行查询以及数据比对的时候,需要有主键和索引方便对比和加快查询速度。 先来看看kettle中的一些组件。

下图是kettle中的一个表输出组件。

kettle中的表输出组件

在该组件里可以指定表名、字段等信息,并且还可以建表的sql语句。打开建表的sql语句,你可以看到该语句里只指定了字段名称和类型,没有指定主外键、约束、和索引。显然,该组件只是完成了数据的输出并没有将表的主键迁移过去。 下图是kettle中纬度更新/查询的组件。

kettle中纬度更新/查询的组件

该组件可以指定输出表名、映射字段、纬度字段、并且指定主键(图中翻译为关键字段),该组件比表输出组件多了一个功能,即指定主键。 从上面两个组件中可以看出,kettle实际上预留了设置主键的接口,具体的接口说明需要查看api或者源代码,只是kettle没有智能的查处输入表的主键字段,而是需要用户在kettle ui界面指定一个主键名称。

如果现在想使用kettle实现异构数据库的数据以及主键和索引的迁移,有没有一个完整方便的解决方案呢?我能想到的解决方案如下: 1.使用kettle向导中的多表复制菜单进行数据库的迁移,这只能实现数据的迁移还需要额外的方法添加主键和索引,你可以手动执行一些脚步添加约束。 2.针对源数据库中的每一张表创建一个转换,转换中使用纬度更新/查询组件,在该主键中指定主键。创建完所有的转换之后,创建一个作业将这些转换串联起来即可。 3.扩展kettle向导中的多表复制菜单里的功能,在该功能创建的作业中添加一些节点用于添加输出表的主键和索引。这些节点可以是执行sql语句的主键,故只需要通过jdbc代码获取添加主键和索引的sql语句。

方案1需要单独执行脚步实现添加主键和索引,创建或生成这些脚步需要些时间;方案2需要针对每个表认为的指定主键,工作量大,而且无法实现添加索引;方案3最容易实现和扩展。

下面是方案3的具体的实现。

首先需要在每一个表的建表语句节点和复制数据节点之后添加一个执行sql语句的节点,该节点用于添加主键和索引。 多表复制向导的核心代码在src-db/org.pentaho.di.ui.spoon.delegates.SpoonJobDelegate.java的public void ripDBWizard()方法中。该方法如下:

public void ripDBWizard(final int no) {
	final List databases = spoon.getActiveDatabases();
	if (databases.size() == 0)
		return;</pre>

	final RipDatabaseWizardPage1 page1 = new RipDatabaseWizardPage1("1",
			databases);
	final RipDatabaseWizardPage2 page2 = new RipDatabaseWizardPage2("2");
	final RipDatabaseWizardPage3 page3 = new RipDatabaseWizardPage3("3",
			spoon.getRepository());
	Wizard wizard = new Wizard() {
		public boolean performFinish() {
			try {
				JobMeta jobMeta = ripDBByNo(no, databases,
					page3.getJobname(), page3.getRepositoryDirectory(),
					page3.getDirectory(), page1.getSourceDatabase(),
					page1.getTargetDatabase(), page2.getSelection());

				if (jobMeta == null)
					return false;

				if (page3.getRepositoryDirectory() != null) {
					spoon.saveToRepository(jobMeta, false);
				} else {
					spoon.saveToFile(jobMeta);
				}

				addJobGraph(jobMeta);
				return true;
			} catch (Exception e) {
				new ErrorDialog(spoon.getShell(), "Error",
						"An unexpected error occurred!", e);
				return false;
			}
		}

		public boolean canFinish() {
			return page3.canFinish();
		}
	};

	wizard.addPage(page1);
	wizard.addPage(page2);
	wizard.addPage(page3);

	WizardDialog wd = new WizardDialog(spoon.getShell(), wizard);
	WizardDialog.setDefaultImage(GUIResource.getInstance().getImageWizard());
	wd.setMinimumPageSize(700, 400);
	wd.updateSize();
	wd.open();
}

该方法主要是创建一个向导,该向导中包括三个向导页,第一个向导页用于选择数据库连接:源数据库和目标数据库连接;第二个向导页用于选表;第三个向导页用于指定作业保存路径。在向导完成的时候,即performFinish()方法里,会根据选择的数据源和表生成一个作业,即JobMeta对象。 创建Jobmeta的方法为:

public JobMeta ripDB(final List databases,final String jobname, final
    RepositoryDirectoryInterface repdir,final String directory, final DatabaseMeta
    sourceDbInfo,final DatabaseMeta targetDbInfo, final String[] tables){
 //此处省略若干代码
}

该方法主要逻辑在下面代码内:

IRunnableWithProgress op = new IRunnableWithProgress() {
	public void run(IProgressMonitor monitor)
	 throws InvocationTargetException, InterruptedException {
	   //此处省略若干代码
	}
}

上面代码中有以下代码用于遍历所选择的表生成作业中的一些节点:

for (int i = 0; i &lt; tables.length &amp;&amp; !monitor.isCanceled(); i++) {
    //此处省略若干代码
}

针对每一张表先会创建一个JobEntrySQL节点,然后创建一个转换JobEntryTrans,可以在创建转换之后再创建一个JobEntrySQL节点,该节点用于添加主键和索引。 这部分的代码如下:

String pksql = JdbcDataMetaUtil.exportPkAndIndex(
		sourceDbInfo, sourceCon, tables[i],
		targetDbInfo, targetCon, tables[i]);
if (!Const.isEmpty(pksql)) {
	location.x += 300;
	JobEntrySQL jesql = new JobEntrySQL(
		BaseMessages.getString(PKG,"Spoon.RipDB.AddPkAndIndex")
			+ tables[i] + "]");
	jesql.setDatabase(targetDbInfo);
	jesql.setSQL(pksql);
	jesql.setDescription(BaseMessages.getString(PKG,
			"Spoon.RipDB.AddPkAndIndex")
			+ tables[i]
			+ "]");
	JobEntryCopy jecsql = new JobEntryCopy();
	jecsql.setEntry(jesql);
	jecsql.setLocation(new Point(location.x, location.y));
	jecsql.setDrawn();
	jobMeta.addJobEntry(jecsql);
	// Add the hop too...
	JobHopMeta jhi = new JobHopMeta(previous, jecsql);
	jobMeta.addJobHop(jhi);
	previous = jecsql;
}

获取添加主键和索引的sql语句,主要是采用jdbc的方式读取两个数据库,判断源数据库的表中是否存在主键和索引,如果有则返回添加主键或索引的sql语句。这部分代码封装在JdbcDataMetaUtil类中。 该代码见:https://gist.github.com/1564353.js

最后的效果图如下:

说明: 1.以上代码使用的是jdbc的方法获取主键或索引,不同的数据库的jdbc驱动实现可能不同而且不同数据库的语法可能不同,故上面代码可能有待完善。 2.如果一个数据库中存在多库并且这多个库中有相同的表,使用上面的代码针对一个表名会查出多个主键或索引。这一点也是可以改善的
目录
相关文章
|
Oracle 前端开发 关系型数据库
kettle开发篇-更新
kettle开发篇-更新
486 1
|
Prometheus 监控 安全
SpringBoot Actuator未授权访问漏洞的解决方法
SpringBoot Actuator未授权访问漏洞的解决方法Actuator 是 SpringBoot 提供的用来对应用系统进行自省和监控的功能模块,借助于 Actuator 开发者可以很方便地对应用系统某些监控指标进行查看、统计等。
28865 0
|
前端开发 JavaScript API
获取react中iframe的里面的图片
获取react中iframe的里面的图片
488 1
|
缓存 Linux 开发工具
CentOS 7- 配置阿里镜像源
阿里镜像官方地址http://mirrors.aliyun.com/ 1、点击官方提供的相应系统的帮助 :2、查看不同版本的系统操作: 下载源1、安装wget yum install -y wget2、下载CentOS 7的repo文件wget -O /etc/yum.
251060 0
|
4月前
|
传感器 物联网 Linux
Python:蓝牙心率广播设备监测(BLE 心率监测器)技术解析与实现
本文探讨了如何使用 Python 脚本与支持蓝牙低功耗(BLE)心率广播的设备交互以获取实时心率数据。重点分析了 BLE 协议、GATT 服务模型,以及具体方法。此外,还讨论了华为手表等设备的兼容性问题。
694 19
kettle开发篇-行转列
kettle开发篇-行转列
838 0
|
JavaScript 前端开发 安全
【Vue3 + Vite】6个非常强大的后台管理项目!开源且免费!
【Vue3 + Vite】6个非常强大的后台管理项目!开源且免费!
|
Java 关系型数据库 数据库连接
MyBatis-Plus介绍及Spring Boot 3集成指南
MyBatis-Plus是一个MyBatis扩展工具,旨在简化Java开发中的CRUD操作。它具有无侵入性、低损耗、强大的CRUD功能、Lambda表达式支持、主键自动生成、ActiveRecord模式、全局操作和内置代码生成器等特点。在Spring Boot 3中集成MyBatis-Plus,需在pom.xml添加依赖,排除特定版本的mybatis-spring,并用@MapperScan注解指定Mapper接口路径。此外,还介绍了如何使用MyBatis-Plus代码生成器自动生成Mapper、Model、Service和Controller层代码,以加速开发。
1749 2
MyBatis-Plus介绍及Spring Boot 3集成指南
|
XML 前端开发 JavaScript
Web的三个主要部分
Web的三个主要部分
1966 1
|
监控 Java API
Java一分钟之-JPA事务管理:PROPAGATION_REQUIRED, PROPAGATION_REQUIRES_NEW等
【6月更文挑战第14天】Java企业开发中,事务管理确保数据一致性,Spring事务管理核心概念包括`PROPAGATION_REQUIRED`和`PROPAGATION_REQUIRES_NEW`。前者在无事务时新建,有事务时加入,常用于保证业务方法在事务中执行。后者始终创建新事务,独立于当前事务,适用于需隔离影响的场景。理解其应用场景和易错点,合理配置事务传播行为,能提升应用的健壮性和性能。通过监控和日志优化事务策略是关键。
326 1