È possibile evitare il filesort?


10

È possibile evitare "Utilizzo temporaneo" e "Utilizzo di filesort" per la seguente query SELECT? Non riesco a capire un modo per farlo.

Ho provato ad aggiungere indici, sia per top_expire che per il programma, ma non ho aiutato Con ORDER BY la query impiega più di 1 secondo e senza essere localizzata è solo 0,003 secondi su localhost

domanda

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;

Schema

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;

Quale versione di MySQL?
Mike Sherrill "Cat Recall",

Su localhost 5.6.11, ma su hosting condiviso sarà mysql-5.1.63-percona
michalzuber

Risposte:


13

I documenti dicono

In alcuni casi, MySQL non può utilizzare gli indici per risolvere ORDER BY, sebbene utilizzi comunque gli indici per trovare le righe che corrispondono alla clausola WHERE. Questi casi includono quanto segue:

e poi continua a elencare molte circostanze che impediscono a MySQL di usare gli indici. Tra questi ci sono

  • Si utilizza ORDER BY su tasti diversi
  • La chiave utilizzata per recuperare le righe non è la stessa utilizzata in ORDER BY

e probabilmente ce ne sono altri.

Per evitare un filesort, devi trovare un modo per ottenere ciò che desideri senza imbatterti in nessuna di quelle (molte) condizioni documentate.

Puoi anche

  • Aumenta la dimensione della variabile sort_buffer_size.
  • Aumenta la dimensione della variabile read_rnd_buffer_size.
  • Utilizzare meno RAM per riga dichiarando le colonne solo grandi quanto devono essere per contenere i valori memorizzati in esse.
  • Cambia tmpdir in modo che punti a un file system dedicato con grandi quantità di spazio libero.

(Stesso link.)

Consulta anche i documenti per l' ottimizzazione delle query LIMIT , che interagiscono con ORDER BY.


1
Grazie per la spiegazione Ho aggiunto il campo ORDER BY all'indice e ora non utilizza filesort.
Adrian P.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.