连接表的性能问题

时间:2012-08-31 00:29:05

标签: hibernate grails

我使用Grails 1.3.7和hibernate 1.3.7与MySQL 5.1。我有以下(简化的)域对象:

class Document {
    String externalId
    Date date
    String url
    String title

    Map metadata = new HashMap()

    def propertyMissing(String key) { return   metadata[key] }
    def propertyMissing(String key, String value) { metadata[key] = value } 
}

当我必须加载一堆这些文档以返回到客户端时,系统最终必须为每个文档运行单独的查询以获取关联的元数据。在合理的机器上花费数十秒来检索带有元数据的几百个文档。不用说,这对于交互式使用来说太慢了。由于我的应用程序想要将所有数据加载到浏览器中以让用户操作它,我无法将查询分成“页面”。

目前,我正在运行的查询如下所示:

Document.executeQuery("select distinct p.document from Posting p where p.topic = :topic", [topic: topic]);

此查询会导致创建一堆Document个实例,这需要很长时间。

Hibernate缓存配置如下:

hibernate {
    cache.use_second_level_cache=true
    cache.use_query_cache=true
    cache.provider_class='net.sf.ehcache.hibernate.EhCacheProvider'
}

有问题的表格是:

mysql> describe document;
+-------------+--------------+------+-----+---------+----------------+
| Field       | Type         | Null | Key | Default | Extra          |
+-------------+--------------+------+-----+---------+----------------+
| id          | bigint(20)   | NO   | PRI | NULL    | auto_increment |
| version     | bigint(20)   | NO   |     | NULL    |                |
| date        | datetime     | YES  |     | NULL    |                |
| external_id | varchar(255) | NO   |     | NULL    |                |
| title       | longtext     | YES  |     | NULL    |                |
| url         | longtext     | NO   |     | NULL    |                |
+-------------+--------------+------+-----+---------+----------------+

mysql> describe document_metadata;
+--------------+---------------+------+-----+---------+-------+
| Field        | Type          | Null | Key | Default | Extra |
+--------------+---------------+------+-----+---------+-------+
| metadata     | bigint(20)    | YES  |     | NULL    |       |
| metadata_idx | varchar(255)  | YES  |     | NULL    |       |
| metadata_elt | varchar(4096) | YES  |     | NULL    |       |
+--------------+---------------+------+-----+---------+-------+

如果不直接在Document中转储元数据表和硬编码字段,我还能做些什么来提高代码的性能吗?

基因

2 个答案:

答案 0 :(得分:0)

也许您可以使用本机sql调用来优化数据检索操作

def sql = '''
  select distinct d.*, m.* 
  from 
    document d 
      join document_metadata m on m.metadata = d.id
      join post p on p.id = d.post_id
  where
    post.topic = :topic'''

def query = session.createSQLQuery(sql)
query.addEntity(com.yourdomain.Document.class)
query.setString("topic", "grails")
def documents = query.list()

显然,选择是不完整的,因为我猜测发布方案和关系

答案 1 :(得分:0)

您可以尝试将元数据放在关联域类中,并依赖于Grails的默认延迟加载关联。然后,您可以更快地加载每个Document的核心信息,并仅加载有关特定Document访问权限的元数据。

class Document {
    // Core non-Map data

    DocumentMetadata metadata

    def propertyMissing(String key) { return metadata?.data?.get(key) }
    def propertyMissing(String key, String value) { 
        if (!metadata) { metadata = new DocumentMetadata() }
        metadata.data[key] = value
    }
}

class DocumentMetadata {
    Map data = new HashMap()
}