`
agapple
  • 浏览: 1583226 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

操作database TableMeta几点内容

 
阅读更多

背景

   今天早上,领导给了我一个任务:在老的系统运行中,DBA反馈说获取database TableMeta操作有点慢,让我分析下基于oracle driver驱动是否可以做下优化。由此引出了本文,仅仅做一个记录。

内容

在补充几点背景知识:

 

1.  老系统介绍

  • 老系统主要负责的业务是做跨机房之间的数据库记录同步,需要获取数据库的table meta信息,进行构造对应的sql。将源数据的columns变化,通过sql方式更新到目标库上。
  • table meta信息分析时,需要获取table的字段,主键,需要支持视图,同义词等表查询

2.  table meta操作原理

jdbcTemplate.execute(new ConnectionCallback() {

            public Object doInConnection(Connection c) throws SQLException, DataAccessException {
                DatabaseMetaData meta = c.getMetaData();
                meta.getTables(catalog, schemaPattern, tableNamePattern, types);
                meta.getColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern);
                meta.getPrimaryKeys(catalog, schema, table);
                return null;
            }
        });

简单一点说,就是利用java.sql.DatabaseMetaData接口中定义的meta信息获取接口进行处理。

 

mysql/oracle实现

oracle实现(oracle.jdbc.driver.OracleDatabaseMetaData):

1. getTables

主要是通过构造对应的SQL进行查询,主要是关联了all_objects 和 all_tab_comments, all_synonyms

SELECT NULL AS table_cat,
o.owner AS table_schem,
o.object_name AS table_name,
o.object_type AS table_type,
c.comments AS remarks
FROM all_objects o, all_tab_comments c
WHERE o.owner LIKE #schema# ESCAPE '/'
AND o.object_name LIKE #table# ESCAPE '/'
AND o.object_type IN ('TABLE', 'SYNONYM', 'VIEW')
AND o.owner = c.owner (+)
AND o.object_name = c.table_name (+)
UNION
SELECT NULL AS table_cat,
s.owner AS table_schem,
s.synonym_name AS table_name,
'SYNONYM' AS table_table_type,
c.comments AS remarks
FROM all_synonyms s, all_objects o, all_tab_comments c
WHERE s.owner LIKE #schema# ESCAPE '/'
AND s.synonym_name LIKE #table# ESCAPE '/'
AND s.table_owner = o.owner
AND s.table_name = o.object_name
AND o.object_type IN ('TABLE', 'VIEW')
AND o.owner = c.owner (+)
AND o.object_name = c.table_name (+)
ORDER BY table_type, table_schem, table_name

注意一下#schema# , #table#的替换,可以使用%进行模糊匹配

 

2. getColumns

主要是通过构造对应的SQL进行查询,主要关联了all_tab_comments, all_synonyms, all_col_comments

SELECT NULL AS table_cat,
DECODE(s.table_owner, NULL, t.owner, s.table_owner) AS table_schem,
DECODE(s.synonym_name, NULL, t.table_name, s.synonym_name) AS table_name,
t.column_name AS column_name,
DECODE (t.data_type, 'CHAR', 1, 'VARCHAR2', 12, 'NUMBER', 3,
'LONG', -1, 'DATE', 93 , 'RAW', -3, 'LONG RAW', -4, 'BLOB', 2004, 'CLOB', 2005, 'BFILE', -13, 'FLOAT', 6, 'TIMESTAMP(6)',
93, 'TIMESTAMP(6) WITH TIME ZONE', -101, 'TIMESTAMP(6) WITH LOCAL TIME ZONE', -102, 'INTERVAL YEAR(2) TO MONTH', -103,
'INTERVAL DAY(2) TO SECOND(6)', -104, 'BINARY_FLOAT', 100, 'BINARY_DOUBLE', 101, 1111) AS data_type,
t.data_type AS type_name,
DECODE (t.data_precision, null, t.data_length, t.data_precision) AS column_size,
0 AS buffer_length,
t.data_scale AS decimal_digits,
10 AS num_prec_radix,
DECODE (t.nullable, 'N', 0, 1) AS nullable,
c.comments AS remarks,
t.data_default AS column_def,
0 AS sql_data_type,
0 AS sql_datetime_sub,
t.data_length AS char_octet_length,
t.column_id AS ordinal_position,
DECODE (t.nullable, 'N', 'NO', 'YES') AS is_nullable
FROM all_tab_columns t , all_col_comments c , all_synonyms s
WHERE (t.owner LIKE #schema# ESCAPE '/' OR
       (s.owner LIKE #schema# ESCAPE '/' AND t.owner = s.table_owner))
        AND (t.table_name LIKE #table# ESCAPE '/' OR
        s.synonym_name LIKE #table# ESCAPE '/')
        AND t.column_name LIKE #column# ESCAPE '/'
        AND t.owner = c.owner (+)  AND t.table_name = c.table_name (+)  AND t.column_name = c.column_name (+)
        AND s.table_name (+) = t.table_name  AND ((DECODE(s.owner, t.owner, 'OK','PUBLIC', 'OK',NULL, 'OK','NOT OK') = 'OK') OR (s.owner LIKE 'SRF' AND t.owner = s.table_owner))
        ORDER BY table_schem, table_name, ordinal_position

注意一下#schema# , #table# , #column#的替换,可以使用%进行模糊匹配

3. getPrimaryKeys

主要是通过构造对应的SQL进行查询,主要关联了 all_cons_columns, all_constraints

SELECT NULL AS table_cat,
c.owner AS table_schem,
c.table_name,
c.column_name,
c.position AS key_seq,
c.constraint_name AS pk_name
FROM all_cons_columns c, all_constraints k
WHERE k.constraint_type = 'P'
  AND k.table_name = #table#  AND k.owner like #schema# escape '/'
  AND k.constraint_name = c.constraint_name
  AND k.table_name = c.table_name
  AND k.owner = c.owner
  ORDER BY column_name

注意一下#schema# , #table# 的替换,可以使用%进行模糊匹配

mysql实现:

有两种获取meta信息的方式

  1. 使用sql语法查询对应的INFORMATION_SCHEMA信息
    SELECT TABLE_SCHEMA AS TABLE_CAT, 
    NULL AS TABLE_SCHEM, TABLE_NAME, 
    CASE WHEN TABLE_TYPE='BASE TABLE' THEN 'TABLE' WHEN TABLE_TYPE='TEMPORARY' THEN 'LOCAL_TEMPORARY' ELSE TABLE_TYPE END AS TABLE_TYPE, 
    TABLE_COMMENT AS REMARKS 
    FROM INFORMATION_SCHEMA.TABLES WHERE 
    TABLE_SCHEMA LIKE #schema# AND TABLE_NAME LIKE #table# AND TABLE_TYPE IN ('BASE TABLE','VIEW','TEMPORARY') 
    ORDER BY TABLE_TYPE, TABLE_SCHEMA, TABLE_NAME
  2. 使用show命令查询对应的meta信息
    SHOW TABLES from retl like 'columns';
    show full columns from columns from retl like 'text%' ;

具体的getTables,getColumns,getPrimaryKeys的实现就不一一贴了,有兴趣的可以自己去看看

优化方案

目前我们新老系统分别使用了ddlutilsschemacrawler两种tablemeta分析方案,最终都是基于DatabaseMetaData进行数据获取。

  • ddlutils:版本1.0(比较早的版本,目前最新为1.3)
  • schemacrawler:版本8.7

两者在实现上没有本质的区别,只不过在schemacrawler在meta信息的获取上可自定义性更强,比如你只关注table,不关注columns,primarykeys,foreignkey等,都可以通过SchemaCrawlerOptions进行指定

 

schemaCrawler例子:

Connection connection = dataSource.getConnection();
DatabaseMetaData databaseMetaData = connection.getMetaData();
String nameSpace = dataMedia.getNamespace();
String name = dataMedia.getName();
if (databaseMetaData.storesUpperCaseIdentifiers()) {// 识别大小写
	nameSpace = nameSpace.toUpperCase();
	name = name.toUpperCase();
}
if (databaseMetaData.storesLowerCaseIdentifiers()) {
	nameSpace = nameSpace.toLowerCase();
	name = name.toLowerCase();
}

final SchemaCrawlerOptions options = new SchemaCrawlerOptions();
options.setSchemaInfoLevel(SchemaInfoLevel.standard());
options.setSchemaInclusionRule(new InclusionRule(nameSpace, InclusionRule.NONE));
options.setTableInclusionRule(new InclusionRule(nameSpace + "." + name, InclusionRule.NONE));
Database database = SchemaCrawlerUtility.getDatabase(connection, options);

Schema[] schemas = database.getSchemas();

for(Schema schema : schemas) {
    for (Table table: Schema.getTables()) {
        Column[] columns = table.getColumns();
    }





}

 

分析本质,主要还是调用DatabaseMediaData进行操作

  MetadataResultSet results = null;
  results = new MetadataResultSet(getMetaData()
	.getTables(unquotedName(catalogName),
			   unquotedName(schemaName),
			   tableNamePattern,
			   TableType.toStrings(tableTypes)));// 调用getTables方法

  while (results.next())
  {
	// "TABLE_CAT", "TABLE_SCHEM"
	final String tableName = quotedName(results.getString("TABLE_NAME"));
	final TableType tableType = results.getEnum("TABLE_TYPE",TableType.unknown);
	final String remarks = results.getString("REMARKS");

	final MutableSchema schema = lookupSchema(catalogName, schemaName);
	.....
	
	if (tableInclusionRule.include(table.getFullName()))
	{
	  table.setType(tableType);
	  table.setRemarks(remarks);

	  schema.addTable(table);
	}
  }

 

通过代码分析,可以看到获取meta信息的方式,总共有3次SQL查询. 

  1. 先获取匹配的表 getTables
  2. 对应的所有字段 getColumns
  3. 获取字段的主键信息 getPrimaryKeys

因此总结一下优化方案:

  • 因为我们是精确的table匹配,所以第一次的匹配表查询SQL可以避免。如果需要优化需要copy schemacrawl的部分代码进行优化。(少一次SQL查询,不过会给代码带来一定的维护成本)
  • oracle driver中针对同义词表的查询,在整个查询过程中都会去关联all_synonyms表,影响查询性能。(不过后续otter4.0上线后,可以支持非同名表的查询,以后可以逐步废弃同义词表的使用,从而优化meta信息的查询)
  • oracle/mysql driver在查询所有字段上都支持批量查询多个表,即意味着我们可以一次性查询相同schema下的所有同步表的信息。 (调整有一定的成本,需要完全自己解析ResultSet的结果对象,支持将Result解析为多个 Table)

最后

本文可能对他人借鉴意义并不是非常大,只为自己做一下记录,项目第一个版本上线后再来做一下对应的优化方案。优化无止境,fighting!!!!!

  • 大小: 11 KB
分享到:
评论
1 楼 sillydog825 2011-12-21  
谢谢,对我很有帮助!

相关推荐

    C#编程 数据库操作应用 Database(源码)(源码)

    C#编程 数据库操作应用 Database(源码)(源码)C#编程 数据库操作应用 Database(源码)(源码)C#编程 数据库操作应用 Database(源码)(源码)C#编程 数据库操作应用 Database(源码)(源码)C#编程 数据库操作应用 Database...

    sybase database维护基本操作

    sybase database维护基本操作

    c#数据库操作Database源码.rar

    c#数据库操作Database源码.rar

    C# Database操作类

    方便的数据库操作类! 可利用数据库存储过程,方便快捷地实现数据库操作。该类封装完美

    Database4.zip

    数据库工具Database4,各种数据库连接方便; 数据库工具Database4,各种数据库连接方便; 数据库工具Database4,各种数据库连接方便; 数据库工具Database4,各种数据库连接方便; 数据库工具Database4,各种数据库连接...

    FUNDAMENTALS OF Database Systems 第7版

    database systems and database applications. Our presentation stresses the funda- mentals of database modeling and design, the languages and models provided by the database management systems, and ...

    H2 Database(H2内存数据库)

    资源包内容列表是我进行H2预研是收集的H2资料,应该是最全面的的了: 1、h2.pdf (H2 API) 2、h2-1.3.173.jar (截止2013-8-15最新的H2.jar) 3、h2-2013-07-28.zip (截止2013-8-15最新的H2服务,包括API\JAR\服务)...

    Oracle Database 21c (oracle-database-ee-21c-1.0-1.ol8.part2.rar)

    Oracle Database 21c 是最新的版本; 21.3 - 企业版(也包括标准版 2) 适用于Linux x86-64位系统。oracle-database-ee-21c-1.0-1.ol8文件分割成 三个 压缩包,必须集齐 三个 文件后才能一起解压一起使用: Oracle ...

    Database Comparer VCL v 5.0

    The Database Comparer VCL represents 100% Delphi VCL components for Borland Delphi / C++Builder. These components allow you to compare and synchronize SQL database objects and table records for many ...

    Oracle Database 12c (winx64_12102_database.part1.rar)

    Oracle Database 12c 适用于Windows 64位系统, winx64_12102_database文件分割成 三个 压缩包,必须集齐 三个 文件后才能一起解压一起使用: Oracle Database 12c (winx64_12102_database.part3.rar) ...

    Six Step Relational Database Design 2nd Edition

    Six-Step Relational Database DesignTM bridges the gaps between database theory, database modeling, and database implementation by outlining a simple but reliable six-step process for accurately ...

    Oracle Database 12c (winx64_12102_database.part3.rar)

    Oracle Database 12c 适用于Windows 64位系统, winx64_12102_database文件分割成 三个 压缩包,必须集齐 三个 文件后才能一起解压一起使用: Oracle Database 12c (winx64_12102_database.part3.rar) ...

    Oracle Database 21c (oracle-database-ee-21c-1.0-1.ol8.part1.rar)

    Oracle Database 21c 是最新的版本; 21.3 - 企业版(也包括标准版 2) 适用于Linux x86-64位系统。oracle-database-ee-21c-1.0-1.ol8文件分割成 三个 压缩包,必须集齐 三个 文件后才能一起解压一起使用: Oracle ...

    Oracle Database 19c (oracle-database-ee-19c.x86_64.part3.rar)

    Oracle Database 19c 是最新的长期版本,支持期限最长; 19.3 - 企业版(也包括标准版 2) 适用于Linux x86-64系统。oracle-database-ee-19c文件分割成 三个 压缩包,必须集齐 三个 文件后才能一起解压一起使用: ...

    DataBaseTool

    小型的数据库操作软件DataBaseTool.exe

    Database2Sharp代码生成器 16.0 破解版

    Database2Sharp是一款主要用于C#代码以及数据库文档生成的工具,软件支持Oracle、SqlServer、MySql、Access、Sqlite等数据库的代码生成,可以生成各种架构代码、生成Winform界面代码、Web界面代码、导出数据库文档、...

    AXPPacker+DataBaseEditor

    AXPPacker+DataBaseEditor

    database2sharp v16 破解版 注册版

    Database2Sharp是一款支持NHibernate、Castle-ActiveRecord、Enterprise Library和 PetShop 框架、 c# 和 Java 代码生成工具,提供为 MS Sql2000,MS Sql2005,Oracle,Mysql,访问支持;代码可以生成各种架构,出口...

    vb database

    vb database vb database vb database vb database

Global site tag (gtag.js) - Google Analytics