Saya telah membaca artikel tentang FORCE
indeks, tetapi bagaimana saya bisa memaksa MySQL ke IGNORE ALL
indeks?
Saya mencoba SELECT * FROM tbl IGNORE INDEX(*)
, tetapi saya tidak berhasil.
Adapun mengapa saya (dan lainnya) perlu melakukan ini: Misalnya, saya perlu merangkum statistik referensi dengan tld seperti ini:
SELECT
count(*) as c,
SUBSTRING
(
domain_name,
LENGTH(domain_name) - LOCATE('.', REVERSE(domain_name)) + 2
) as tld
FROM `domains_import`
IGNORE INDEX(domain_name)
GROUP BY tld
ORDER BY c desc
LIMIT 100
... tapi saya selalu harus melihat indeks apa yang didefinisikan atau menentukan indeks apa yang akan digunakan melalui Jelaskan. Akan sangat berguna untuk sekadar menulis IGNORE INDEX ALL
dan tidak peduli.
Adakah yang tahu sintaks atau hack? (Puluhan baris melalui tabel definisi MySQL benar-benar bukan jalan pintas).
Ditambahkan dari diskusi obrolan :
Bechmark:
tidak ada indeks = 148,5 detik
dengan indeks = 180 detik dan masih berjalan dengan Mengirim data Array SSD sangat kuat, sehingga Anda hampir tidak peduli dengan cache data ...
Definisi untuk tolok ukur:
CREATE TABLE IF NOT EXISTS `domains_import` (
`domain_id` bigint(20) unsigned NOT NULL,
`domain_name` varchar(253) CHARACTER SET ascii COLLATE ascii_bin NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `domains_import`
ADD PRIMARY KEY (`domain_id`),
ADD UNIQUE KEY `domain_name` (`domain_name`);
ALTER TABLE `domains_import`
MODIFY `domain_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT;
InnoDB, tes dengan indeks (tanpa USE INDEX () atau serupa) masih berjalan, 250 detik, saya baru saja membunuhnya.
LEFT JOIN
saya miliki. `USE INDEX ()` membuat MySQL melakukan pemindaian tabel pada tabel 20K dan 1-ke-1JOIN
alih-alih melintasi 500 baris di antara dua indeks. Mendapat 20x lebih cepat.Anda juga bisa menanamkan
WHERE 1=1
ypercube baru saja bertanya padaku
Ya, tetapi Anda telah memberikan MySQL permintaan yang benar-benar bodoh.
1=1
akan kembali ke Indeks Clustered. Meskipun demikian, masih ada cara lain, tetapi harus sedikit berbahaya bagi Pengoptimal.Ini akan membuang setiap indeks di bawah bus pasti karena nilai setiap baris untuk
domain_name
banyak diperiksa. Jikadomain_name
diindeks, Anda harus memilih kolom untukWHERE column_name=column_name
yang tidak diindeks sama sekali.Saya baru saja mencoba ini di atas meja besar di server Pementasan
Tidak ada indeks yang dipilih
sumber
WHERE id+0 = id*1
indeks akan tetap digunakan, dan tambahanUsing where
akan muncul.Dengan asumsi Anda memiliki dua indeks ini:
Maka tidak masalah apa yang dilakukan pengoptimal; itu harus memindai pada dasarnya jumlah barang yang identik.
Kasus 1: Ini melakukan pemindaian tabel (atau menggunakan domain_id): Ini akan memindai pasangan (id, nama), menemukan semua nama, melakukan SUBSTRING..LOKASI, GROUP BY, dan akhirnya ORDER BY. GROUP BY dan ORDER BY mungkin masing-masing membutuhkan tabel dan file tmp. Periksa
EXPLAIN SELECT ...
apakah itu benar.Kasus 2: Itu melakukan pemindaian indeks (dari domain_name): Indeks itu sebenarnya mengandung pasangan (nama, id) - karena InnoDB secara implisit menempatkan PK di akhir setiap kunci sekunder. Sisa dari paralel pemrosesan Kasus 1.
Satu hal bisa berbeda - ukuran dua BTrees. Lakukan
SHOW TABLE STATUS LIKE domains_import
untuk melihat Data_length (untuk Kasus 1) dan Index_length (untuk Kasus 2). BTree yang lebih besar akan lebih lambat.Hal lain dapat berbeda - caching. Apa nilainya
innodb_buffer_pool_size
? Berapa banyak RAM yang Anda miliki? Bisakah Data (atau Indeks) terkandung dalam buffer pool. (Atau 37%, karena ini adalah pemindaian tabel / indeks?) Jika cocok, maka jalankan kueri dua kali. Waktu kedua akan sekitar 10 kali lebih cepat karena tidak memukul disk (caching).Jika ini adalah tugas satu kali, SSD akan membantu. Jika tidak, dan Anda dapat men-cache seluruh tabel, maka itu tidak akan membantu setelah buffer_pool dimuat.
sumber