Apakah mungkin untuk menghindari filesort?

10

Apakah mungkin untuk menghindari 'Menggunakan sementara' dan 'Menggunakan filesort' untuk kueri SELECT berikut? Saya tidak tahu cara untuk melakukannya.

Saya mencoba menambahkan indeks, baik untuk top_expire dan program, tetapi tidak membantu dengan ORDER OLEH kueri membutuhkan waktu lebih dari 1 detik dan tanpa suara itu hanya 0,003 detik di localhost

Pertanyaan

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;

Skema

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
sumber
Apa versi MySQL?
Mike Sherrill 'Cat Recall'
Di localhost 5.6.11, tetapi pada shared hosting itu akan menjadi mysql-5.1.63-percona
michalzuber

Jawaban:

13

Dokumen mengatakan

Dalam beberapa kasus, MySQL tidak dapat menggunakan indeks untuk menyelesaikan ORDER BY, meskipun masih menggunakan indeks untuk menemukan baris yang cocok dengan klausa WHERE. Kasus-kasus ini meliputi:

dan kemudian lanjutkan ke daftar banyak keadaan yang mencegah MySQL dari menggunakan indeks. Diantaranya adalah

  • Anda menggunakan ORDER OLEH pada tombol yang berbeda
  • Kunci yang digunakan untuk mengambil baris tidak sama dengan yang digunakan dalam ORDER BY

dan mungkin ada yang lain.

Untuk menghindari filesort, Anda harus menemukan cara untuk mendapatkan apa yang Anda inginkan tanpa mengalami salah satu dari banyak kondisi yang didokumentasikan.

Anda juga bisa

  • Tambah ukuran variabel sort_buffer_size.
  • Tambah ukuran variabel read_rnd_buffer_size.
  • Gunakan lebih sedikit RAM per baris dengan mendeklarasikan kolom hanya sebesar yang dibutuhkan untuk menyimpan nilai yang tersimpan di dalamnya.
  • Ubah tmpdir untuk menunjuk ke sistem file khusus dengan sejumlah besar ruang kosong.

(Tautan yang sama.)

Lihat juga dokumen untuk Mengoptimalkan Pertanyaan LIMIT , yang berinteraksi dengan ORDER BY.

Mike Sherrill 'Cat Recall'
sumber
1
Terima kasih untuk penjelasannya Saya telah menambahkan bidang ORDER BY ke dalam indeks dan sekarang tidak menggunakan filesort.
Adrian P.