2011-11-07 21 views
11

Son son günlerde, sorgumu optimize eden garip bir şey fark ettim. Ben böyle bir şey yapar basit bir sorgu var: Ben MySQL herhangi dizini kullanarak değildi farkMYSQL - DEĞİL vs var = yanlış

SELECT id,name,amount FROM reservations WHERE NOT canceled ORDER BY name ASC 

, bu yüzden bazı deneyler yapmaya başladı. Yanlışlıkla "iptal edilmedi" "iptal edildi" ile değiştirildi ve sonra Mysql "iptal edildi" dizin olarak kullanmaya başladı.

SELECT ... FROM reservations WHERE canceled ORDER BY ... 

aynı sonucu: Bundan sonra tam tersini kullanarak çalıştı! Bunu "iptal edilen = doğru" olarak değiştirdiğimde, dizin tekrar çalışır.

Soruma soru: HOW COME ?! "Zarif" yolu "DEĞİL" kullanmıyor mu? Her neyse, bir fark yaratmasını beklemiyordum.

Motor olarak InnoDB kullanıyorum, ancak aynı sonucu MyISAM kullanarak elde ediyorum. Birisi bir şeyleri netleştirebilir mi? Teşekkürler.

Düzenleme: Tablo yapısı bir dizin kullanıyor olsa

CREATE TABLE `reservations` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `trip_code` varchar(10) DEFAULT NULL, 
    `departure_date` date DEFAULT NULL, 
    `amount` float DEFAULT NULL, 
    `name` varchar(45) DEFAULT NULL, 
    `canceled` tinyint(1) NOT NULL DEFAULT '0', 
    `created_date` date NOT NULL, 
    `creator_user` int(11) NOT NULL DEFAULT '1', 
    `last_update_user` int(11) NOT NULL DEFAULT '1', 
    PRIMARY KEY (`id`), 
    KEY `trip_code` (`trip_code`), 
    KEY `departure_date` (`departure_date`), 
    KEY `created_date` (`created_date`), 
    KEY `canceled` (`canceled`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=123181 ; 
+0

hangi sürümü kullanıyorsunuz? – neworld

+0

Sunucu sürümü: 5.1.43-community – Phoenix

+0

Tablonun DDL'sini yükleyebilir misiniz? –

cevap

2

Ben MYSQL aşina değilim, ama mantıklı düşünme, ben bunu böyle anlıyorum:
endeksi gibidir Telefon rehberi, "Cohen" aradığınızda, hemen alabilirsiniz.
NOT: "Cohen" NOT: Her girişin üzerinden geçmek ve "Cohen" den farklı olup olmadığını kontrol etmeniz gerekir.
spesifik değeri için arıyorsanız, sadece bunun için görünüyor. Ve NOT kullanırken, tinyint(1) içine sığabilecek başka bir değer arar (anladığım kadarıyla sadece 1 veya 0 değil mi?).

+0

Sanırım “WHERE iptal edildi” nin de bir endeks kullanmadığı sorusunu işaret ediyorlar. Açık olmasa da "Aynı sonuç" ne ifade eder. –

+0

Sanırım, "iptal edilen" değeri 1, 2 veya 3 olduğunda geçersiz ... Yani hala ** belirli bir değer değil ** tahmin –

+0

Sütunun bildirildiği gerçeğini göz ardı ederek 'tinyint (1)' '' WHERE canceled = true' için de aynı özgüllük yoktur. –

3

, endeks (ister inan ister inanma) sorgu yavaş yapabilir. Bu biraz garip, ancak dizin seçiciliği ile ilgili. Genellikle boole tipi sütunlarda sunulur. .

Sanki descrbed oluyor.

"Bir alanın farklı değerlerdir Nasıl 0-1, arasında bir sayı da yüzde olarak düşünmek rağmen olduğu 1 değeri ya % 100, alandaki her değer "Bu dikkate almak önemlidir

benzersiz olduğu anlamına gelir nedeniyle bu derste:

"MySQL, maliyet tabanlı bir iyileştiriciye sahiptir. Bu, MySQL'in değerini sorgulamanın farklı yollarının maliyetini hesapladığı ve daha sonra en ucuz olanını seçtiği anlamına gelir. Eh, maliyetlerin hesaplanması bir eksik bilimdir. Yani bir tahmini alınır ve tahmini bazen yanlış "

Düz basit:.

Eğer aradığınız veri (örneğin aynı değere sahip az ya da çok% 20 sahipse iptal sonra, sadece bir tablo taraması yapmak için basit) masanızdaki% 40'ına sahip

DÜZENLEME:. sorunuza gelince

, AÇIKLAYINIZ MySQL usin olduğunu söyler g bir indeks. Ancak, iyi olmayabilir, optimizasyonunuzun daha iyi olup olmadığını not etmenin tek yolu, performansı test etmektir. Ayrıca, bu dizini korumak için INSERT, UPDATE ve DELETE işlemlerinin kosullarını düşünün. İndeksli ve indekssiz bazı profiller yapın.

bu bir göz atın:

+0

Cevabınız için teşekkür ederiz. Bunu şimdi anlıyorum. Yine de, soru hala devam ediyor. "var1 DEĞİL", "var1 = yanlış" dan nasıl farklıdır? – Phoenix

+0

Haklısın üzgünüm. Cevabı ben düzenledim. – santiagobasulto

1
SELECT * 
FROM 
(SELECT 1 AS C, 0 AS X UNION ALL 
SELECT 2 AS C, 1 AS X UNION ALL 
SELECT 3 AS C, 2 AS X) T 
WHERE X=true 

İade

'2', '1' 

Ve

SELECT * 
FROM 
(SELECT 1 AS C, 0 AS X UNION ALL 
SELECT 2 AS C, 1 AS X UNION ALL 
SELECT 3 AS C, 2 AS X) T 
WHERE X 

İade

'2', '1' 
'3', '2' 

Yani birinci durumda trueartığını alır gibi görünüyor 0 ve sonra aranabilir bir yüklemde kullanılırken, ikinci durumda sütun değeri dolaylı olarak dökülmüştür. Örtük oyuncular genellikle bir koşulu değişmez hale getirir. WHERE canceled için size

+----+-------------+--------------+------+---------------+-----+---------+-----+------+-----------------------------+ 
| id | select_type | table  | type | possible_keys | key | key_len | ref | rows |   Extra   | 
+----+-------------+--------------+------+---------------+-----+---------+-----+------+-----------------------------+ 
| 1 | SIMPLE  | reservations | ALL |    |  |   |  | 2 | Using where; Using filesort | 
+----+-------------+--------------+------+---------------+-----+---------+-----+------+-----------------------------+ 

olsun Oysa WHERE canceled = true ile sorgu için açıklamak planı baktığımızda

Yani o bile olarak canceled üzerinde indeksini kabul edemeyeceğine görünür

+----+-------------+--------------+------+---------------+----------+---------+-------+------+-----------------------------+ 
| id | select_type | table  | type | possible_keys | key | key_len | ref | rows |   Extra   | 
+----+-------------+--------------+------+---------------+----------+---------+-------+------+-----------------------------+ 
| 1 | SIMPLE  | reservations | ref | canceled  | canceled |  1 | const | 1 | Using where; Using filesort | 
+----+-------------+--------------+------+---------------+----------+---------+-------+------+-----------------------------+ 

verir Bu durumda olası seçenek.