mysql的order by與where出現的好玩事

CREATE TABLE employees ( 
emp_no INT(11) NOT NULL, 
birth_date DATE NOT NULL, 
first_name VARCHAR(14) NOT NULL, 
last_name VARCHAR(16) NOT NULL, 
gender ENUM(‘M’,’F’) NOT NULL, 
hire_date DATE NOT NULL, 
PRIMARY KEY (emp_no

COLLATE=’utf8’ 
ENGINE=InnoDB;

INSERT INTO employees (emp_nobirth_datefirst_namelast_namegenderhire_date) VALUES (10001, ‘1953-09-02’, ‘Georgi’, ‘Facello’, ‘M’, ‘1986-06-26’); 
INSERT INTO employees (emp_nobirth_datefirst_namelast_namegenderhire_date) VALUES (10002, ‘1964-06-02’, ‘Bezalel’, ‘Simmel’, ‘F’, ‘1985-11-21’); 
INSERT INTO employees (emp_nobirth_datefirst_namelast_namegenderhire_date) VALUES (10003, ‘1959-12-03’, ‘Parto’, ‘Bamford’, ‘M’, ‘1986-08-28’); 
INSERT INTO employees (emp_nobirth_datefirst_namelast_namegenderhire_date) VALUES (10004, ‘1954-05-01’, ‘Chirstian’, ‘Koblick’, ‘M’, ‘1986-12-01’); 
INSERT INTO employees (emp_nobirth_datefirst_namelast_namegenderhire_date) VALUES (10005, ‘1955-01-21’, ‘Kyoichi’, ‘Maliniak’, ‘M’, ‘1989-09-12’); 
INSERT INTO employees (emp_nobirth_datefirst_namelast_namegenderhire_date) VALUES (10006, ‘1953-04-20’, ‘Anneke’, ‘Preusig’, ‘F’, ‘1989-06-02’); 
INSERT INTO employees (emp_nobirth_datefirst_namelast_namegenderhire_date) VALUES (10007, ‘1957-05-23’, ‘Tzvetan’, ‘Zielinski’, ‘F’, ‘1989-02-10’); 
INSERT INTO employees (emp_nobirth_datefirst_namelast_namegenderhire_date) VALUES (10008, ‘1958-02-19’, ‘Saniya’, ‘Kalloufi’, ‘M’, ‘1994-09-15’); 
INSERT INTO employees (emp_nobirth_datefirst_namelast_namegenderhire_date) VALUES (10011, ‘1972-02-29’, ‘He’, ‘Rick’, ‘M’, ‘1991-02-20’); 
INSERT INTO employees (emp_nobirth_datefirst_namelast_namegenderhire_date) VALUES (64887, ‘1961-05-15’, ‘Rafols’, ‘Suomi’, ‘F’, ‘1987-06-05’); 
INSERT INTO employees (emp_nobirth_datefirst_namelast_namegenderhire_date) VALUES (64888, ‘1962-05-16’, ‘Kristof’, ‘Marchegay’, ‘F’, ‘1988-11-10’); 
INSERT INTO employees (emp_nobirth_datefirst_namelast_namegenderhire_date) VALUES (64889, ‘1953-05-08’, ‘Emdad’, ‘Pauthner’, ‘M’, ‘1985-09-07’); 
INSERT INTO employees (emp_nobirth_datefirst_namelast_namegenderhire_date) VALUES (64890, ‘1957-08-21’, ‘Leni’, ‘Kilgore’, ‘M’, ‘1995-08-31’); 
INSERT INTO employees (emp_nobirth_datefirst_namelast_namegenderhire_date) VALUES (64891, ‘1954-09-27’, ‘Ioana’, ‘Pepe’, ‘F’, ‘1990-08-19’); 
INSERT INTO employees (emp_nobirth_datefirst_namelast_namegenderhire_date) VALUES (64892, ‘1964-12-05’, ‘Mayumi’, ‘Tyugu’, ‘F’, ‘1988-03-19’); 
INSERT INTO employees (emp_nobirth_datefirst_namelast_namegenderhire_date) VALUES (64893, ‘1953-11-27’, ‘Yoshimitsu’, ‘Billawala’, ‘F’, ‘1986-06-07’); 
INSERT INTO employees (emp_nobirth_datefirst_namelast_namegenderhire_date) VALUES (64894, ‘1955-09-19’, ‘Mori’, ‘Weedman’, ‘F’, ‘1999-01-29’); 
INSERT INTO employees (emp_nobirth_datefirst_namelast_namegenderhire_date) VALUES (64895, ‘1962-02-24’, ‘Dietrich’, ‘Foote’, ‘M’, ‘1988-08-07’); 
INSERT INTO employees (emp_nobirth_datefirst_namelast_namegenderhire_date) VALUES (64896, ‘1960-12-31’, ‘Ingemar’, ‘Schieder’, ‘M’, ‘1995-10-25’); 
INSERT INTO employees (emp_nobirth_datefirst_namelast_namegenderhire_date) VALUES (64897, ‘1956-04-24’, ‘Aksel’, ‘Denna’, ‘M’, ‘1986-08-31’); 
INSERT INTO employees (emp_nobirth_datefirst_namelast_namegenderhire_date) VALUES (64898, ‘1961-04-13’, ‘Sudhanshu’, ‘Hutton’, ‘M’, ‘1996-02-09’); 
1:實現row_number. 
這裏寫圖片描述 
2:取前3條: 
這裏寫圖片描述 
3:對first_name排序取前三條: 
這裏寫圖片描述 
在沒有排序時得到的事正確的三條數據,但是排序後得到的是21條(全部數據),奇怪。 
猜測: 
(1)執行了where但是在排序時是將所有的數據都拿出來排序的 
(2)沒有執行where,直接排序輸出了。即跳過了where. 
看explain: 
這裏寫圖片描述 
MySQL官方手冊解釋: 
Using where 
A WHERE clause is used to restrict which rows to match against the next table or send to the client. Unless you specifically intend to fetch or examine all rows from the table, you may have something wrong in your query if the Extra value is not Using where and the table join type is ALL or index.

Using filesort 
MySQL must do an extra pass to find out how to retrieve the rows in sorted order. The sort is done by going through all rows according to the join type and storing the sort key and pointer to the row for all rows that match the WHERE clause. 
然後看到使用了filesort是要使用外部空間進行排序的,這裏我是這樣想的,sql執行是從右到左的所以應該是order by跳過了where,所以猜測是(2). 
因爲使用了filesort所以建立first_name索引試下: 
這裏寫圖片描述 
MySQL官方手冊解釋: 
Using index 
The column information is retrieved from the table using only information in the index tree without having to do an additional seek to read the actual row. This strategy can be used when the query uses only columns that are part of a single index. 
可以看到建立了first_name索引之後沒有filesort了,而且數據也正確了。 
所以這裏沒有了filesort,數據正確所以應該是猜測(1)成立。 
在高性能mysql第三版中的6.7.9節中有這樣一段話:因爲order by引入了文件排序,而where條件是在文件排序操作之前取值的,所以這條查詢會返回表中的全部記錄,解決這個問題的辦法是讓變量的賦值和取值發生在執行查詢的同一階段:如圖: 
這裏寫圖片描述 
但是我還是支持做個子查詢,這樣就不用考慮太多了。哈哈,有點懶了。 
不過高性能mysql第三版這個解說和我的想法不一致。先放着,下次深入理解。有知道同學希望討論下。 
感謝羣裏的大白菜和explain 
對於filesort的優化可以在網上找下,這裏有比較好的 
http://www.ccvita.com/169.html 
http://blog.csdn.net/yangyu112654374/article/details/4251624 
http://bbs.chinaunix.net/thread-1020877-1-1.html

高性能mysql第三版書籍下載:http://download.csdn.net/detail/u011575570/9224323


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章