Можно ли избежать сортировки файлов?

10

Можно ли избежать «Использование временного» и «Использование файловой сортировки» для следующего запроса SELECT? Я не могу найти способ сделать это.

Я попытался добавить индексы, как для top_expire, так и для программы, но это не помогло. С ORDER BY запрос занимает более 1 секунды, а без него - всего 0,003 секунды на localhost.

запрос

SELECT ad.*, p.link
    FROM (SELECT ad.*
        FROM mod_ad ad 
        JOIN mod_ad_auta auta ON ad.id = auta.ad_id
        WHERE ad.active != 0 AND ad.usr_active != 0 AND ad.expire > 1371151608  AND ad.cat_id = '1' AND ad.price <= '10000' 
          AND auta.rocnik BETWEEN '1950' AND '2013' 
          AND auta.km BETWEEN '0' AND '500000'
        ORDER BY top_expire DESC, program DESC,  ad.id DESC  LIMIT 0,10) as ad
JOIN pages p ON ad.page_id=p.page_id;

схема

CREATE TABLE `mod_ad` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` int(10) unsigned NOT NULL,
  `page_id` int(10) unsigned NOT NULL,
  `cat_id` int(10) unsigned NOT NULL,
  `subcat_id` int(10) unsigned NOT NULL,
  `program` tinyint(1) unsigned NOT NULL,
  `region_id` int(10) unsigned NOT NULL,
  `zone_id` int(10) unsigned NOT NULL,
  `city_id` int(10) unsigned NOT NULL,
  `sort` enum('firm','priv') NOT NULL,
  `type` enum('predaj','kúpa','výmena','darujem','hľadám','ponúkam','iné') NOT NULL,
  `condition` varchar(24) NOT NULL,
  `name` varchar(128) NOT NULL,
  `desc` text NOT NULL,
  `location` varchar(128) NOT NULL,
  `keywords` varchar(255) NOT NULL,
  `price` decimal(10,2) NOT NULL,
  `price_type` varchar(20) NOT NULL,
  `cperson` varchar(128) NOT NULL,
  `firmname` varchar(128) NOT NULL,
  `zip` varchar(5) NOT NULL,
  `email` varchar(255) NOT NULL,
  `tel` varchar(20) NOT NULL,
  `tel2` varchar(20) NOT NULL,
  `web` varchar(255) NOT NULL,
  `video` varchar(255) NOT NULL,
  `marked_expire` int(11) unsigned NOT NULL,
  `top_expire` int(11) unsigned NOT NULL,
  `ad_hot_expire` int(11) unsigned NOT NULL,
  `ad_border_expire` int(11) unsigned NOT NULL,
  `ad_heading_expire` int(11) unsigned NOT NULL,
  `ad_weblink_expire` int(11) unsigned NOT NULL,
  `active` int(10) unsigned NOT NULL,
  `usr_active` int(10) unsigned NOT NULL,
  `added` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `archive` int(10) unsigned NOT NULL,
  `expire` int(11) unsigned NOT NULL,
  `token` varchar(32) NOT NULL,
  `views` mediumint(9) NOT NULL,
  `ip` varchar(15) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `user_id` (`user_id`),
  KEY `page_id` (`page_id`),
  KEY `cat_id` (`cat_id`),
  KEY `region_id` (`region_id`),
  KEY `zone_id` (`zone_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

CREATE TABLE `mod_ad_auta` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `ad_id` int(10) unsigned NOT NULL,
  `model` int(10) unsigned NOT NULL,
  `rocnik` smallint(5) unsigned NOT NULL,
  `palivo` varchar(10) NOT NULL,
  `karoseria` varchar(12) NOT NULL,
  `km` mediumint(8) unsigned NOT NULL,
  `prevodovka` varchar(12) NOT NULL,
  `farba` varchar(16) NOT NULL,
  `metaliza` tinyint(1) unsigned NOT NULL,
  `obsah` smallint(5) unsigned NOT NULL,
  `vykon` smallint(5) unsigned NOT NULL,
  `vybava` text NOT NULL,
  PRIMARY KEY (`id`),
  KEY `ad_id` (`ad_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
michalzuber
источник
Какая версия MySQL?
Майк Шеррилл 'Cat Recall'
На локальном хосте 5.6.11, но на виртуальном хостинге это будет mysql-5.1.63-percona
michalzuber

Ответы:

13

Документы говорят

В некоторых случаях MySQL не может использовать индексы для разрешения ORDER BY, хотя он все еще использует индексы для поиска строк, которые соответствуют предложению WHERE. Эти случаи включают в себя следующее:

а затем перейдите к списку многих обстоятельств, которые мешают MySQL использовать индексы. Среди них есть

  • Вы используете ORDER BY на разных клавишах
  • Ключ, используемый для выборки строк, не совпадает с ключом, используемым в ORDER BY

и есть, вероятно, другие.

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

Вы также можете

  • Увеличьте размер переменной sort_buffer_size.
  • Увеличьте размер переменной read_rnd_buffer_size.
  • Используйте меньше ОЗУ на строку, объявляя столбцы настолько большими, насколько это необходимо для хранения значений, хранящихся в них.
  • Измените tmpdir, чтобы он указывал на выделенную файловую систему с большим количеством свободного места.

(Та же ссылка.)

Также см. Документы по оптимизации запросов LIMIT , которые взаимодействуют с ORDER BY.

Майк Шеррилл 'Cat Recall'
источник
1
Спасибо за объяснение. Я добавил поле ORDER BY в индекс, и теперь он не использует сортировку файлов.
Адриан П.