2011-11-07 57 views
11

在過去的幾天裏,我注意到一些奇怪的事情,優化我的查詢。 我有一個簡單的查詢,這確實是這樣的:MYSQL - 不與var = false

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

我的mysql沒有使用任何索引注意到了,所以我就開始做一些實驗。 我偶然用「取消= false」取代了「NOT取消」,然後,Mysql開始使用「取消」作爲索引。 之後,我試着用相反的:

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

同樣的結果!當我將其更改爲「取消=真」時,該索引再次起作用。

我的問題是:怎麼回事?不是使用「不」而是「優雅」的方式?無論如何,我沒有想到它會有所作爲。

我使用InnoDB作爲引擎,但使用MyISAM得到了相同的結果。 有人可以澄清一些事情嗎? 謝謝。

編輯:表結構

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

你使用哪個版本? – neworld

+0

Server版本:43年1月5日,社區 – Phoenix

+0

你能張貼表的DDL。 –

回答

2

我不熟悉的MySQL,但思維邏輯,我的理解是這樣的:
指數就像是一個電話簿,當你在搜索「科恩」時,你可以馬上得到它。
但是,如果你正在尋找「科恩」,你必須每個條目跑過來,並檢查它是否是從「科恩」不同。
所以,當你正在尋找特定值,它看起來只是爲了它。當您使用,它會尋找可以裝進tinyint(1)任何其他值(按照我的理解,這只是10沒有,是吧?)。

+0

我認爲他們的疑問,'WHERE canceled'不使用索引也表示。雖然不清楚「同樣的結果」是指什麼。 –

+0

嗯,我想,'WHERE當'canceled'的值是1,2或3 canceled'是真的......所以它仍然不是一個**特定值**斷言 –

+0

忽略該列聲明的事實'tinyint(1)''WHERE cancelled = true'的情況是相同的。 –

3

即使它使用索引,索引(信不信由你)可以使你的查詢速度較慢。這有點奇怪,但它與索引選擇性有關。它通常用布爾類型的列表示。

它descrbed,如:。

「字段的值不同是如何正是從0-1, 一些,雖然你也可以把它當作一個百分比值1或 100%,這意味着在該領域的每個值是唯一的」

考慮是非常重要的becouse:

「MySQL有一個基於成本的優化器。這意味着MySQL計算 執行查詢的不同方式的成本,然後選擇最便宜的一個。那麼,計算成本是一個不精確的科學。因此,一個 估計拍攝,而且估計是錯誤的,有時「

樸素簡單:

如果你正在尋找的數據具有相同的值或多或少20%(例如,取消了有你的表的40%),那麼,它的簡單,只是做一個表掃描

編輯:

關於你的問題,講解告訴你,MySQL是全光照g指數。但是,它可能不是很好,唯一的方法來注意你的優化是否更好是測試性能。另外,考慮INSERT,UPDATE和DELETE操作的costo以保持該索引。在索引和不索引的情況下進行一些分析。

看看這個:

+0

感謝您的回答。我現在明白了。無論如何,這個問題依然存在。 「NOT VAR1」與「VAR1 = false」有什麼不同? – Phoenix

+0

你說得對,對不起。我編輯了答案。 – 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 

返回

'2', '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 

返回

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

如此看來,在第一種情況下true被轉換爲int,然後用於可搜索謂詞中,而在第二種情況下,列值是隱式轉換的。隱式轉換通常使條件不可變。

望着與WHERE canceled = true您的查詢的解釋計劃給

+----+-------------+--------------+------+---------------+----------+---------+-------+------+-----------------------------+ 
| 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 | 
+----+-------------+--------------+------+---------------+----------+---------+-------+------+-----------------------------+ 

而對於WHERE canceled

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

這樣看來,它甚至不能考慮canceled指數爲在這種情況下可能的選擇。