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;

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.


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.
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.