提高连接的查询性能并使用order by

时间:2011-02-20 18:11:36

标签: mysql hibernate grails

我正在使用Grails框架进行项目,该项目使用Hibernate进行ORM。 Grails支持命名查询,这些查询转换为休眠标准。我一直在使用P6Spy和SQLProfiler来尝试提高其中一个命名查询的性能。

问题是,当我运行没有order by子句的查询时,它运行大约.1200秒。当我添加order by子句时,它会增加到15秒。

这是(大致)最终结果查询的样子:

Select 
    * 
from 
    article
left outer join 
    feed_articles 
on 
    article.id = feed_articles.article_id
where 
    ( 
        feed_articles.feed_id = 1 or 
        feed_articles.feed_id = 43 or 
        feed_articles.feed_id = 67
    )
order by 
    article.updated
limit
    50

如果有任何专家阅读,这里是文章域名的精简版:

static hasMany = [articleFeeds: ArticleFeed]

Date updated

static namedQueries = {

    containedInFeeds { feedList ->
        articleFeeds{
            or{
                feedList.each{ feed ->
                    eq("feed", feed)
                }
            }
        }
    }
}

Grails Note 我通过添加

尝试了这两点
orderBy("updated", "desc") 
maxResults("50") 

在域中,并尝试

Article.containedInFeeds().listDistinct(max: 50, sort: "updated", order: "desc")

在控制器中,但生成的SQL似乎都是相同的。

我已尝试在更新字段的文章表中添加索引,但这不会导致性能提升。

文章表约有190,000个项目。

我还对查询进行了解释(作为我发现建议的博客文章),并注意到没有订单,只有“使用位置”被列为附加内容。当使用“使用Where,使用临时,使用Filesort”命令时,都列出了。

我猜我没有正确创建索引,mysql实例需要进行一些调整,或者两者兼而有之。

修改

更多信息

我一直在网上搜索有关索引的更多信息,特别是关于何时使用连接和顺序。我能找到的最接近的写作是:http://hackmysql.com/case5但该网站说它不再维护,我猜这些技术已经过时了(至少它们对我不起作用)。我真的很想了解如何/为什么要将事情编入索引,而不是简单地给出答案。

以下是请求的表定义和解释输出。

文章表

CREATE TABLE  `mydb`.`article` (
    `id` bigint(20) NOT NULL AUTO_INCREMENT,
    `version` bigint(20) NOT NULL,
    `link` varchar(255) DEFAULT NULL,
    `image_id` bigint(20) DEFAULT NULL,
    `unique_id` varchar(255) DEFAULT NULL,
    `author` varchar(255) DEFAULT NULL,
    `title` varchar(255) DEFAULT NULL,
    `source` varchar(255) DEFAULT NULL,
    `updated` datetime DEFAULT NULL,
    `description` varchar(1000) DEFAULT NULL,
    `date_created` datetime NOT NULL,
    PRIMARY KEY (`id`),
    KEY `FK317B135BE74D38` (`image_id`),
    KEY `Updated_Idx_Test` (`id`,`updated`) USING BTREE,
    CONSTRAINT `FK317B135BE74D38` FOREIGN KEY (`image_id`) REFERENCES `remote_image`  (`id`)
    )
 ENGINE=InnoDB AUTO_INCREMENT=195939 DEFAULT CHARSET=latin1;

_Feed_Articles表_

CREATE TABLE  `mydb`.`feed_articles` (
    `id` bigint(20) NOT NULL AUTO_INCREMENT,
    `version` bigint(20) NOT NULL,
    `article_id` bigint(20) NOT NULL,
    `feed_id` bigint(20) NOT NULL,
    PRIMARY KEY (`id`) USING BTREE,
    KEY `FK9E0121145D70E756` (`article_id`),
    KEY `FK9E012114A51FD776` (`feed_id`),  
    CONSTRAINT `FK9E0121145D70E756` FOREIGN KEY (`article_id`) REFERENCES `article` (`id`),  
    CONSTRAINT `FK9E012114A51FD776` FOREIGN KEY (`feed_id`) REFERENCES `feed` (`id`)
    ) 
ENGINE=InnoDB AUTO_INCREMENT=231684 DEFAULT CHARSET=latin1;

解释输出

我稍微修改了查询,通过将where子句更改为从10个feed_id中拉出来:

 feed_articles.feed_id = 1 or
 .
 .
 .
 feed_articles.feed_id = 10

输出:

+----+-------------+-----------+--------+---------------------------------------+--------------------+---------+----------------------------+-------+----------------------------------------------+
| id | select_type | table     | type   | possible_keys                         | key                | key_len | ref                        | rows  | Extra                                        |
+----+-------------+-----------+--------+---------------------------------------+--------------------+---------+----------------------------+-------+----------------------------------------------+
|  1 | SIMPLE      | feed_item | range  | FK9E0121145D70E756,FK9E012114A51FD776 | FK9E012114A51FD776 | 8       | NULL                       | 51909 | Using where; Using temporary; Using filesort |
|  1 | SIMPLE      | item      | eq_ref | PRIMARY,Updated_Idx_Test              | PRIMARY            | 8       | wiumidev.feed_item.item_id |     1 |                                              |
+----+-------------+-----------+--------+---------------------------------------+--------------------+---------+----------------------------+-------+----------------------------------------------+

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

是的,当然。您需要创建索引。 尝试在feed_articles.feed_id(第一个)和article.id,article.updated(第二个)上创建复合索引。

相关问题