Оптимизация MySQL ORDER BY во многих таблицах

0

Таблицы:

CREATE TABLE IF NOT EXISTS `posts` (

  `post_n` int(10) NOT NULL auto_increment,
  `id` int(10) default NULL,
  `date` datetime NOT NULL default '0000-00-00 00:00:00',

  PRIMARY KEY  (`post_n`,`visibility`),
  KEY `id` (`id`),
  KEY `date` (`date`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

CREATE TABLE IF NOT EXISTS `subscriptions` (

  `subscription_n` int(10) NOT NULL auto_increment,
  `id` int(10) NOT NULL,
  `subscribe_id` int(10) NOT NULL,

  PRIMARY KEY  (`subscription_n`),
  KEY `id` (`id`),
  KEY `subscribe_id` (`subscribe_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

Query:

SELECT posts.* FROM posts, subscriptions 

WHERE posts.id=subscriptions.subscribe_id AND subscriptions.id=1 

ORDER BY date DESC LIMIT 0, 15

Это так медленно, потому что используемые индексы "id", "subscribe_id", но не индекс "дата", поэтому упорядочение происходит очень медленно.

Есть ли какие-либо опции для изменения запроса, индексов, архитектуры?

  • 0
    никаких изменений в скорости :(
Теги:
order
query-optimization

2 ответа

1
Лучший ответ

Возможные улучшения:

Во-первых, вы получите пару микросекунд за запрос, если вы назовете свои поля вместо использования сообщений SELECT. *, который вызывает поиск схемы. Измените свой запрос на:

SELECT posts.post_n, posts.id, posts.date 
FROM posts, subscriptions 
WHERE posts.id=subscriptions.subscribe_id 
  AND subscriptions.id=1 
ORDER BY date DESC 
LIMIT 0, 15

Далее, для этого требуется MySQL 5.1 или новее, но вам может потребоваться разделить ваши таблицы. Вы можете рассмотреть раздел KEY для обеих таблиц.

Это должно помочь вам начать. http://dev.mysql.com/doc/refman/5.1/en/partitioning-types.html

например.

SET SQL_MODE = 'ANSI';
-- to allow default date
CREATE TABLE IF NOT EXISTS `posts` (
  `post_n` int(10) NOT NULL auto_increment,
  `id` int(10) default NULL,
  `date` datetime NOT NULL default '0000-00-00 00:00:00',
  PRIMARY KEY  (`post_n`,`id`),
  KEY `id` (`id`),
  KEY `date` (`date`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_bin
PARTITION BY KEY(id) PARTITIONS 32;
--
CREATE TABLE IF NOT EXISTS `subscriptions` (
  `subscription_n` int(10) NOT NULL auto_increment,
  `id` int(10) NOT NULL,
  `subscribe_id` int(10) NOT NULL,
  PRIMARY KEY  (`subscription_n`,`subscribe_id`),
  KEY `id` (`id`),
  KEY `subscribe_id` (`subscribe_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_bin
PARTITION BY KEY(subscribe_id) PARTITIONS 32;

Мне пришлось немного изменить свой первичный ключ. Поэтому, будьте осторожны, это НЕ МОЖЕТ РАБОТАТЬ для вас. Пожалуйста, проверьте его и убедитесь. Надеюсь, это правда. Обязательно запустите sysbench против старых и новых структур/запросов, чтобы сравнить результаты перед тем, как перейти к производству. : -)

  • 0
    о да, это что-то новое для меня. Я обновлю версию MySQL и протестирую ее, спасибо! :)
  • 0
    после добавления скорость разбиения увеличилась в 2, это хорошо. Мне нужно проверить это больше, спасибо.
Показать ещё 6 комментариев
0

Если вы можете изменить таблицу, вы можете добавить индекс с несколькими полями, содержащий как идентификатор, так и дату. (или изменить один из существующих ключей, чтобы содержать их оба).

Если вы не можете внести изменения в базу данных, и если вы знаете, что ваш результирующий набор будет небольшим, вы можете заставить его использовать определенный именованный ключ с USE KEY(name). После этого заказ будет выполнен после факта, как раз на возвращенных reslts.

Надеюсь, что это поможет.

  • 0
    Я сделал, как вы сказали, но безрезультатно. Скорость еще 0,1
  • 0
    Без заказа 0,0013. Я в отчаянии

Ещё вопросы

Сообщество Overcoder
Наверх
Меню