最近做了一次MySQL所謂的”海量數據”查詢性能分析.
說明, MyISAM引擎, dt表示時間字段使用datetime類型, it表示時間字段使用int類型.
首先生成100K個UNIX時間戳(int), 然后隨機選取10M次, 每一次往6個表里插入一條記錄(當time字段是datetime類型時, 做類型轉換). 所以每一個表都有10M條記錄. ext1和ext2字段會用隨機的字符串填充.
使用的查詢SQL語句如:
select SQL_NO_CACHE count(*) from it where time>10000;select SQL_NO_CACHE count(*) from dt where time>from_unixtime(10000);select SQL_NO_CACHE * from it where time>10000 order by time limit 1;select SQL_NO_CACHE * from it use key(PRIMARY) where time>10000 order by id limit 1;
SQL_NO_CACHE用于消除查詢結果緩存的影響. use key用于指定查詢時使用的索引. 統計每一條SQL的執行時間(單位s)和滿足WHERE條件的記錄總數(total), it-tm表示在dt表上執行SQL的耗時, 并explain得到key和extra, 結果如下.
where total select orderby key it-tm dt-tm it2-tm dt2-tm it3-tm dt3-tm extra time>10000 8999050 count(*) time 3.52 4.28 3.74 4.49 3.53 4.47 where; index count(time) time 3.44 4.00 3.69 4.36 3.56 4.26 where; index count(id) NULL 1.44 1.92 4.30 4.60 4.79 4.98 where * time time 0.00 0.00 0.00 0.00 0.00 0.00 where * id time 14.81 15.38 19.37 20.30 20.94 21.42 where; filesort * id PK 0.00 0.03 0.00 0.02 0.00 0.04 where time>50000 4987990 count(*) 1.90 2.36 2.02 2.41 1.99 2.42 count(time) 1.90 2.23 2.01 2.32 1.96 2.29 count(id) 1.48 1.91 4.25 4.61 4.80 5.12 * time 0.00 0.00 0.00 0.00 0.00 0.00 * id 8.15 8.77 10.74 11.36 11.59 11.79 * id 0.00 0.00 0.00 0.00 0.00 0.00 time>80000 1991982 count(*) 0.76 0.95 0.83 0.98 0.80 1.00 count(time) 0.77 0.91 0.81 0.91 0.83 0.92 count(id) 1.38 1.86 4.17 4.49 4.71 5.02 * time 0.00 0.00 0.00 0.00 0.00 0.00 * id 3.26 3.44 4.26 4.51 4.56 4.76 * id 0.00 0.00 0.00 0.00 0.00 0.00 time>99900 10871 count(*) 0.00 0.00 0.00 0.01 0.01 0.00 count(time) 0.01 0.01 0.01 0.00 0.01 0.01 count(id) 0.01 0.01 0.02 0.03 0.02 0.02 * time 0.00 0.00 0.00 0.00 0.00 0.00 * id 0.02 0.02 0.03 0.03 0.03 0.03 * id 0.00 0.00 0.00 0.00 0.00 0.00count(*), count(time)和count(id)的對比. 結果有較大變化. 當表的字段只有2個且查詢條件較寬松(即符合條件的記錄數較多)時, count(id)比count(*)快很多, 但是, 當表中還有其它的字段時, count(id)反而更慢了. 雖然id是主鍵, time是索引列, 但是select count(id) where time并沒有用到索引, 而是進行全表掃描. 當對count(*)進行ignore key(time)時, 查詢時間和count(id)相同.證明當結果集較大時索引導致查詢變慢,應該是全表掃描進行的是連續的磁盤IO和內存操作, 而使用索引是進行隨機的磁盤IO和內存操作, 并且MyISAM存儲索引的BTree結構占用更多的空間. 當WHERE條件約束更嚴格, total的值小到一定程度時, 全表掃描比使用索引慢, 因為索引極大減少了磁盤IO和內存操作.
排序字段和索引的使用. 當有排序且LIMIT(偏移為0)時,如果查詢時使用的索引不是排序字段的索引, 那么速度非常慢. 當偏移不為0時, 如果使用排序列的索引, 要考慮偏移可能導致掃描的記錄數, 所以應該根據情況選取合適的索引.
判斷符合條件的記錄是否存在, 使用select * limit 1速度要比select count(*)計數快得多.
時間字段類型的選擇. int比datetime快, 但差距不是很明顯.
無論如何, 條件限制得越嚴格, 查詢就會越快.
另外, 根據隨機id更新時, 大約能達到5K行/s.
列的先后順序對查詢性能的影響也非常大.
bitsCN.com聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com