Est-il possible d'éviter le tri de fichiers?

10

Est-il possible d'éviter «Utiliser temporaire» et «Utiliser le tri de fichiers» pour la requête SELECT suivante? Je ne peux pas trouver un moyen de le faire.

J'ai essayé d'ajouter des index, à la fois pour top_expire et pour le programme, mais je n'ai pas aidé Avec l'ORDRE PAR la requête prend plus de 1 seconde et sans elle, c'est juste 0,003 secondes sur localhost

Requete

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;

Schéma

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
la source
Quelle version de MySQL?
Mike Sherrill 'Cat Recall'
Sur localhost 5.6.11, mais sur l'hébergement partagé, ce sera mysql-5.1.63-percona
michalzuber

Réponses:

13

Les docs disent

Dans certains cas, MySQL ne peut pas utiliser d'index pour résoudre ORDER BY, bien qu'il utilise toujours des index pour rechercher les lignes qui correspondent à la clause WHERE. Ces cas sont les suivants:

puis passez à la liste de nombreuses circonstances qui empêchent MySQL d'utiliser des index. Parmi eux,

  • Vous utilisez ORDER BY sur différentes clés
  • La clé utilisée pour récupérer les lignes n'est pas la même que celle utilisée dans ORDER BY

et il y en a probablement d'autres.

Pour éviter un tri de fichiers, vous devez trouver un moyen d'obtenir ce que vous voulez sans rencontrer aucune de ces (nombreuses) conditions documentées.

Vous pouvez également

  • Augmentez la taille de la variable sort_buffer_size.
  • Augmentez la taille de la variable read_rnd_buffer_size.
  • Utilisez moins de RAM par ligne en déclarant les colonnes aussi grandes que nécessaire pour contenir les valeurs qui y sont stockées.
  • Modifiez tmpdir pour pointer vers un système de fichiers dédié avec de grandes quantités d'espace libre.

(Même lien.)

Consultez également la documentation sur l' optimisation des requêtes LIMIT , qui interagit avec ORDER BY.

Mike Sherrill 'Cat Recall'
la source
1
Merci pour l'explication. J'ai ajouté le champ ORDER BY à l'index et maintenant il n'utilise pas le tri de fichiers.
Adrian P.