Performance 使用datanucleus创建持久化管理器时,数据类型查询过多

Performance 使用datanucleus创建持久化管理器时,数据类型查询过多,performance,jdbc,jdo,Performance,Jdbc,Jdo,我们发现使用datanucleus和postgresql jdbc连接到远程postgres数据库的性能非常差。原因是生成了许多查询来查询数据类型表:pg_catalog.pg_type 我们编写了一个小程序,如下所示,并将datanucleus、JDO和postgres jdbc JAR添加到类路径中,它将在创建持久化管理器时从pg_catalog.pg_类型中获取每个条目 测试程序: Map properties = new HashMap(); properties.put("javax.

我们发现使用datanucleus和postgresql jdbc连接到远程postgres数据库的性能非常差。原因是生成了许多查询来查询数据类型表:pg_catalog.pg_type

我们编写了一个小程序,如下所示,并将datanucleus、JDO和postgres jdbc JAR添加到类路径中,它将在创建持久化管理器时从pg_catalog.pg_类型中获取每个条目

测试程序:

Map properties = new HashMap();
properties.put("javax.jdo.PersistenceManagerFactoryClass", "org.datanucleus.jdo.JDOPersistenceManagerFactory");
properties.put("datanucleus.storeManagerType", "rdbms");
properties.put("datanucleus.ConnectionDriverName", "org.postgresql.Driver");
properties.put("datanucleus.ConnectionURL", "jdbc:postgresql://xxxx:5432/mydb");
properties.put("datanucleus.ConnectionUserName", "xxx");
properties.put("datanucleus.ConnectionPassword", "xxx");

properties.put("datanucleus.autoCreateSchema", "false");
properties.put("datanucleus.autoCreateTables", "false");
properties.put("datanucleus.autoCreateColumns", "false");
properties.put("datanucleus.autoCreateConstraints", "false");

properties.put("datanucleus.validateSchema", "false");
properties.put("datanucleus.validateTables", "false");
properties.put("datanucleus.validateConstraints", "false");
properties.put("datanucleus.validateColumns", "false");
properties.put("datanucleus.metadata.validate", "false");

PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory(properties);
PersistenceManager pm = PersistenceManagerFactoryUtils.getPersistenceManager(pmf, true);
Query query = pm.newQuery("javax.jdo.query.SQL", "select * from dblanguage limit 10");
Object result = query.execute();
System.out.println("completed");
以下是我们在数据库日志文件中找到的已执行查询的一部分:

51 HKT LOG: execute <unnamed>: SELECT t.typlen FROM pg_catalog.pg_type t, pg_catalog.pg_namespace n WHERE t.typnamespace=n.oid AND t.typname='name' AND n.nspname='pg_catalog'
2011-11-18 15:44:51 HKT LOG: execute <unnamed>: SELECT t.typname,t.oid FROM pg_catalog.pg_type t JOIN pg_catalog.pg_namespace n ON (t.typnamespace = n.oid) WHERE n.nspname != 'pg_toast'
2011-11-18 15:44:51 HKT LOG: execute <unnamed>: SELECT 1 FROM pg_catalog.pg_type WHERE typname = $1 AND typinput='array_in'::regproc
2011-11-18 15:44:51 HKT DETAIL: parameters: $1 = 'int2vector'
2011-11-18 15:44:51 HKT LOG: execute <unnamed>: SELECT typname FROM pg_catalog.pg_type WHERE oid = $1
2011-11-18 15:44:51 HKT DETAIL: parameters: $1 = '22'
2011-11-18 15:44:51 HKT LOG: execute <unnamed>: SELECT 1 FROM pg_catalog.pg_type WHERE typname = $1 AND typinput='array_in'::regproc
2011-11-18 15:44:51 HKT DETAIL: parameters: $1 = 'regproc'
2011-11-18 15:44:51 HKT LOG: execute <unnamed>: SELECT typname FROM pg_catalog.pg_type WHERE oid = $1
2011-11-18 15:44:51 HKT DETAIL: parameters: $1 = '24'
2011-11-18 15:44:51 HKT LOG: execute <unnamed>: SELECT 1 FROM pg_catalog.pg_type WHERE typname = $1 AND typinput='array_in'::regproc
2011-11-18 15:44:51 HKT DETAIL: parameters: $1 = 'tid'
2011-11-18 15:44:51 HKT LOG: execute <unnamed>: SELECT typname FROM pg_catalog.pg_type WHERE oid = $1
2011-11-18 15:44:51 HKT DETAIL: parameters: $1 = '27'
2011-11-18 15:44:51 HKT LOG: execute <unnamed>: SELECT 1 FROM pg_catalog.pg_type WHERE typname = $1 AND typinput='array_in'::regproc
2011-11-18 15:44:51 HKT DETAIL: parameters: $1 = 'xid'
2011-11-18 15:44:51 HKT LOG: execute <unnamed>: SELECT typname FROM pg_catalog.pg_type WHERE oid = $1
2011-11-18 15:44:51 HKT DETAIL: parameters: $1 = '28'
2011-11-18 15:44:51 HKT LOG: execute S_1: SELECT 1 FROM pg_catalog.pg_type WHERE typname = $1 AND typinput='array_in'::regproc
2011-11-18 15:44:51 HKT DETAIL: parameters: $1 = 'cid'
2011-11-18 15:44:51 HKT LOG: execute S_2: SELECT typname FROM pg_catalog.pg_type WHERE oid = $1
2011-11-18 15:44:51 HKT DETAIL: parameters: $1 = '29'
......
51 HKT日志:执行:从pg_catalog.pg_类型t、pg_catalog.pg_名称空间n中选择t.typlen,其中t.typnespace=n.oid和t.typname='name'以及n.nspname='pg_目录'
2011-11-18 15:44:51 HKT日志:执行:从pg_catalog中选择t.typname,t.oid。pg_类型t加入pg_catalog.pg_命名空间n ON(t.typnespace=n.oid),其中n.nspname!='pg_吐司'
2011-11-18 15:44:51 HKT日志:执行:从pg_catalog.pg_type中选择1,其中typname=$1,typinput='array_in'::regproc
2011-11-18 15:44:51香港时间细节:参数:$1='int2vector'
2011-11-18 15:44:51 HKT日志:执行:从pg_catalog.pg_type中选择类型名称,其中oid=$1
2011-11-18 15:44:51香港时间细节:参数:$1='22'
2011-11-18 15:44:51 HKT日志:执行:从pg_catalog.pg_type中选择1,其中typname=$1,typinput='array_in'::regproc
2011-11-18 15:44:51香港时间细节:参数:$1='regproc'
2011-11-18 15:44:51 HKT日志:执行:从pg_catalog.pg_type中选择类型名称,其中oid=$1
2011-11-18 15:44:51香港时间细节:参数:$1='24'
2011-11-18 15:44:51 HKT日志:执行:从pg_catalog.pg_type中选择1,其中typname=$1,typinput='array_in'::regproc
2011-11-18 15:44:51香港时间细节:参数:$1='tid'
2011-11-18 15:44:51 HKT日志:执行:从pg_catalog.pg_type中选择类型名称,其中oid=$1
2011-11-18 15:44:51香港时间细节:参数:$1='27'
2011-11-18 15:44:51 HKT日志:执行:从pg_catalog.pg_type中选择1,其中typname=$1,typinput='array_in'::regproc
2011-11-18 15:44:51香港时间细节:参数:$1='xid'
2011-11-18 15:44:51 HKT日志:执行:从pg_catalog.pg_type中选择类型名称,其中oid=$1
2011-11-18 15:44:51香港时间细节:参数:$1='28'
2011-11-18 15:44:51 HKT日志:执行S_1:从pg_catalog.pg_类型中选择1,其中typname=$1,typinput='array_in'::regproc
2011-11-18 15:44:51香港时间细节:参数:$1='cid'
2011-11-18 15:44:51 HKT日志:执行S_2:从pg_catalog.pg_type中选择typname,其中oid=$1
2011-11-18 15:44:51香港时间细节:参数:$1='29'
......
由于执行的此类查询太多(数千),因此会降低性能。有人知道如何解决这个问题吗?谢谢

在我进一步跟踪到datanucleus库之后,下面是stacktrace,它显示了如何调用从rdbms检索数据类型信息:

RDBMSSchemaHandler.getRDBMSTypesInfo(Connection) line: 359  
RDBMSSchemaHandler.getSchemaData(Object, String, Object[]) line: 167    
PostgreSQLAdapter(DatabaseAdapter).initialiseTypes(StoreSchemaHandler, ManagedConnection) line: 462 
PostgreSQLAdapter.initialiseTypes(StoreSchemaHandler, ManagedConnection) line: 119  
RDBMSStoreManager.<init>(ClassLoaderResolver, OMFContext) line: 304 
NativeConstructorAccessorImpl.newInstance0(Constructor, Object[]) line: not available [native method]   
NativeConstructorAccessorImpl.newInstance(Object[]) line: not available 
DelegatingConstructorAccessorImpl.newInstance(Object[]) line: not available 
Constructor<T>.newInstance(Object...) line: not available   
NonManagedPluginRegistry.createExecutableExtension(ConfigurationElement, String, Class[], Object[]) line: 587   
PluginManager.createExecutableExtension(String, String, String, String, Class[], Object[]) line: 300    
FederationManager.initialiseStoreManager(ClassLoaderResolver) line: 173 
FederationManager.<init>(ClassLoaderResolver, OMFContext) line: 74  
JDOPersistenceManagerFactory(ObjectManagerFactoryImpl).initialiseStoreManager(ClassLoaderResolver) line: 139    
JDOPersistenceManagerFactory.freezeConfiguration() line: 583    
JDOPersistenceManagerFactory.createPersistenceManagerFactory(Map) line: 286 
JDOPersistenceManagerFactory.getPersistenceManagerFactory(Map) line: 182    
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]  
NativeMethodAccessorImpl.invoke(Object, Object[]) line: not available   
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: not available   
Method.invoke(Object, Object...) line: not available    
JDOHelper$16.run() line: 1958   
AccessController.doPrivileged(PrivilegedExceptionAction<T>) line: not available [native method] 
JDOHelper.invoke(Method, Object, Object[]) line: 1953   
JDOHelper.invokeGetPersistenceManagerFactoryOnImplementation(String, Map<?,?>, Map<?,?>, ClassLoader) line: 1159    
JDOHelper.getPersistenceManagerFactory(Map<?,?>, Map<?,?>, ClassLoader) line: 803   
JDOHelper.getPersistenceManagerFactory(Map<?,?>) line: 698  
PersistenceManagerFactoryTest.createPersistenceManagerFactory() line: 33    
PersistenceManagerFactoryTest.main(String[]) line: 86   
RDBMSSchemaHandler.getRDBMSTypesInfo(连接)行:359
RDBMSSchemaHandler.getSchemaData(对象,字符串,对象[])行:167
PostgreSQLAdapter(DatabaseAdapter).InitialieSetypes(StoreSchemaHandler,ManagedConnection)行:462
PostgreSQLAdapter.InitialieSetypes(StoreSchemaHandler,ManagedConnection)行:119
RDBMSStoreManager.(ClassLoaderResolver,OMFContext)行:304
NativeConstructorAccessorImpl.newInstance0(构造函数,对象[])行:不可用[本机方法]
NativeConstructorAccessorImpl.newInstance(对象[])行:不可用
DelegatingConstructorAccessorImpl.newInstance(对象[])行:不可用
构造函数.newInstance(对象…)行:不可用
NonManagedPluginRegistry.createExecutableExtension(配置元素,字符串,类[],对象[])行:587
PluginManager.createExecutableExtension(字符串,字符串,字符串,字符串,类[],对象[])行:300
FederationManager.InitialieStoreManager(ClassLoaderResolver)行:173
联邦管理器。(ClassLoaderResolver,OMFContext)行:74
JDOperationResistenceManagerFactory(ObjectManagerFactoryImpl).InitialieStoreManager(ClassLoaderResolver)行:139
jdoperistencemanagerFactory.freezeConfiguration()行:583
JDOPersistenceManagerFactory.createPersistenceManagerFactory(映射)行:286
JDOPersistenceManagerFactory.getPersistenceManagerFactory(映射)行:182
NativeMethodAccessorImpl.invoke0(方法、对象、对象[])行:不可用[本机方法]
NativeMethodAccessorImpl.invoke(对象,对象[])行:不可用
DelegatingMethodAccessorImpl.invoke(对象,对象[])行:不可用
调用(对象,对象…)行:不可用
JDOHelper$16.run()行:1958
AccessController.doPrivileged(PrivilegedExceptionAction)行:不可用[本机方法]
调用(方法、对象、对象[])行:1953
invokeGetPersistenceManagerFactoryOnImplementation(字符串、映射、映射、类加载器)行:1159
getPersistenceManagerFactory(映射、映射、类加载器)行:803
JDOHelper.getPersistenceManagerFactory(映射)行:698
PersistenceManagerFactoryTest.createPersistenceManagerFactory()行:33
PersistenceManagerFactoryTest.main(字符串[])行:86

您可以很容易地确定,DataNucleus(在其日志中定义其查询)不会调用这些查询。也许看看您的JDBC驱动程序……stacktrace显示DataNucleus从数据库中获取类型信息,然后将其缓存。结论:DataNucleus不会发出此类调用。它只调用DatabaseMetaData.getTypeInfo。JDBC驱动程序是发出SQL调用的驱动程序,并且在提供此数据存储支持哪些JDBC类型方面应该做得更好。如果您认为可以提供一个SQL来提供与getTypeInfo应该提供的信息相同的信息,那么您可以轻松地提供它。我对Postgresql 8+没有这样的性能问题,谢谢您的回复。这是否意味着获取类型信息对于JDBC是必要的?如果应用服务器和数据库服务器