Повышение производительности запросов при объединениях и использовании порядка за счет - PullRequest
0 голосов
/ 20 февраля 2011

Я использую инфраструктуру Grails для проекта, который использует Hibernate для ORM. Grails поддерживает именованные запросы, которые переводятся в критерии гибернации. Я использовал P6Spy и SQLProfiler, чтобы попытаться повысить производительность одного из этих именованных запросов.

Проблема в том, что когда я запускаю запрос без предложения order by, он выполняется примерно за 1200 секунд. Когда я добавляю заказ по предложению, он увеличивается до 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

В случае, если кто-то из экспертов Grails читает, вот урезанная версия домена статьи:

static hasMany = [articleFeeds: ArticleFeed]

Date updated

static namedQueries = {

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

Грааль Примечание Я попробовал это как, добавив

orderBy("updated", "desc") 
maxResults("50") 

в домене и попытавшись

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

в контроллере, но результирующий SQL кажется одинаковым в любом случае.

Я попытался добавить индекс к таблице статей для обновленного поля, но это не привело к повышению производительности.

Таблица артикулов содержит примерно 190 000 наименований.

Я также выполнил объяснение по запросам (как я рекомендовал в сообщении в блоге) и заметил, что без заказа только в качестве дополнения указывается только «Использование где». При использовании упорядочены по «Использование где, Использование временного, Использование сортировки файлов» все перечислены.

Я предполагаю, что я не создал индекс должным образом, что экземпляр 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 table_

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 Ответ

1 голос
/ 20 февраля 2011

Да, конечно. Вам нужно создать индексы. Попробуйте создать на feed_articles.feed_id (первый) и составной индекс на article.id, article.updated (второй).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...