Ist es möglich, Dateisortierung zu vermeiden?

10

Ist es möglich, "Verwenden von temporären" und "Verwenden von Dateisortierung" für die folgende SELECT-Abfrage zu vermeiden? Ich kann keinen Weg finden, es zu tun.

Ich habe versucht, Indizes sowohl für top_expire als auch für das Programm hinzuzufügen, aber es hat nicht geholfen. Bei ORDER BY dauert die Abfrage mehr als 1 Sekunde und ohne sie sind es nur 0,003 Sekunden auf localhost

Abfrage

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;
michalzuber
quelle
Welche Version von MySQL?
Mike Sherrill 'Cat Recall'
Auf localhost 5.6.11, aber auf Shared Hosting wird es mysql-5.1.63-percona sein
michalzuber

Antworten:

13

Die Dokumente sagen

In einigen Fällen kann MySQL keine Indizes verwenden, um ORDER BY aufzulösen, obwohl es weiterhin Indizes verwendet, um die Zeilen zu finden, die mit der WHERE-Klausel übereinstimmen. Diese Fälle umfassen Folgendes:

Führen Sie anschließend viele Umstände auf, die MySQL daran hindern, Indizes zu verwenden. Unter ihnen sind

  • Sie verwenden ORDER BY für verschiedene Tasten
  • Der zum Abrufen der Zeilen verwendete Schlüssel ist nicht derselbe wie der im ORDER BY verwendete

und es gibt wahrscheinlich andere.

Um eine Dateisortierung zu vermeiden, müssen Sie einen Weg finden, um das zu erreichen, was Sie möchten, ohne auf eine dieser (vielen) dokumentierten Bedingungen zu stoßen.

Du kannst auch

  • Erhöhen Sie die Größe der Variablen sort_buffer_size.
  • Erhöhen Sie die Größe der Variablen read_rnd_buffer_size.
  • Verwenden Sie weniger RAM pro Zeile, indem Sie Spalten nur so groß deklarieren, wie sie sein müssen, um die darin gespeicherten Werte zu speichern.
  • Ändern Sie tmpdir so, dass es auf ein dediziertes Dateisystem mit viel freiem Speicherplatz verweist.

(Gleicher Link.)

Siehe auch Dokumente zur Optimierung von LIMIT-Abfragen , die mit ORDER BY interagieren.

Mike Sherrill 'Cat Recall'
quelle
1
Danke für die Erklärung. Ich habe das Feld ORDER BY zum Index hinzugefügt und jetzt wird kein Dateisort verwendet.
Adrian P.