MySQL處理達到百萬級數據時,如何優化?

1.兩種查詢引擎查詢速度(myIsam 引擎	)
	InnoDB 中不保存表的具體行數,也就是說,執行select count(*) from table時,InnoDB要掃描一遍整個表來計算有多少行。
	MyISAM只要簡單的讀出保存好的行數便可。
	注意的是,當count(*)語句包含 where條件時,兩種表的操做有些不一樣,InnoDB類型的表用count(*)或者count(主鍵),加上where col 條件。其中col列是表的主鍵以外的其餘具備惟一約束索引的列。這樣查詢時速度會很快。就是能夠避免全表掃描。
	總結:
		mysql 在300萬條數據(myisam引擎)狀況下使用 count(*) 進行數據總數查詢包含條件(正確設置索引)運行時間正常。對於常常進行讀取的數據咱們建議使用myIsam引擎。
2.百萬數據下mysql分頁問題
	在開發過程當中咱們常常會使用分頁,核心技術是使用limit進行數據的讀取,在使用limit進行分頁的測試過程當中,獲得如下數據:
		select * from news order by id desc limit 0,10
		耗時0.003秒
		select * from news order by id desc limit 10000,10
		耗時0.058秒
		select * from news order by id desc limit 100000,10 
		耗時0.575秒
		select * from news order by id desc limit 1000000,10
		耗時7.28秒
	咱們驚訝的發現mysql在數據量大的狀況下分頁起點越大查詢速度越慢,100萬條起的查詢速度已經須要7秒鐘。這是一個咱們沒法接受的數值!
	改進方案 1
		select * from news 
		where id >  (select id from news order by id desc  limit 1000000, 1)
		order by id desc 
		limit 0,10
	查詢時間 0.365秒,提高效率是很是明顯的!!原理是什麼呢???
	咱們使用條件對id進行了篩選,在子查詢 (select id from news order by id desc limit 1000000, 1) 中咱們只查詢了id這一個字段比起select * 或 select 多個字段 節省了大量的查詢開銷!

	改進方案2
	適合id連續的系統,速度極快!
		select * from news 
		where id  between 1000000 and 1000010 
		order by id desc
	不適合帶有條件的、id不連續的查詢。速度很是快!
3.	百萬數據下mysql條件查詢、分頁查詢的注意事項
	接上一節,咱們加上查詢條件:
		select id from news 
		where cate = 1
		order by id desc 
		limit 500000 ,10 
		查詢時間 20 秒
	好恐怖的速度!!利用第一節知識進行優化:
		select * from news
		where cate = 1 and id > (select id from news where cate = 1 order by id desc limit 500000,1 ) 
		order by id desc 
		limit 0,10 
		查詢時間 15 秒
	優化效果不明顯,條件帶來的影響仍是很大!在這樣的狀況下不管咱們怎麼去優化sql語句就沒法解決運行效率問題。那麼換個思路:創建一個索引表,只記錄文章的id、分類信息,咱們將文章內容這個大字段分割出去。
		表 news2 [ 文章表 引擎 myisam 字符集 utf-8 ]
		-------------------------------------------------
		id	int	11	主鍵自動增長
		cate	int	11	索引
	在寫入數據時將2張表同步,查詢是則可使用news2 來進行條件查詢:
		select * from news
		where cate = 1 and id > (select id from news2 where cate = 1 order by id desc limit 500000,1 ) 
		order by id desc 
		limit 0,10
	注意條件 id > 後面使用了news2 這張表!
	運行時間 1.23秒,咱們能夠看到運行時間縮減了近20倍!!數據在10萬左右是查詢時間能夠保持在0.5秒左右,是一個逐步接近咱們可以容忍的值!
	可是1秒對於服務器來講依然是一個不能接受的值!!還有什麼能夠優化的辦法嗎??咱們嘗試了一個偉大的變化:
	將 news2 的存儲引擎改變爲innodb,執行結果是驚人的!
		select * from news
		where cate = 1 and id > (select id from news2 where cate = 1 order by id desc limit 500000,1 ) 
		order by id desc 
		limit 0,10
	只須要 0.2秒,很是棒的速度。爲何會有怎麼大的差異呢?請觀看下一章 mysql存儲引擎詳解。
4.mysql存儲引擎 myIsam和innodb的區別	
	MySQL有多種存儲引擎,MyISAM和InnoDB是其中經常使用的兩種。這裏介紹關於這兩種引擎的一些基本概念(非深刻介紹)。
		MyISAM是MySQL的默認存儲引擎,基於傳統的ISAM類型,支持全文搜索,但不是事務安全的,並且不支持外鍵。每張MyISAM表存放在三個文件中:frm 文件存放表格定義;數據文件是MYD (MYData);索引文件是MYI (MYIndex)。
		InnoDB是事務型引擎,支持回滾、崩潰恢復能力、多版本併發控制、ACID事務,支持行級鎖定(InnoDB表的行鎖不是絕對的,若是在執行一個SQL語句時MySQL不能肯定要掃描的範圍,InnoDB表一樣會鎖全表,如like操做時的SQL語句),以及提供與Oracle類型一致的不加鎖讀取方式。InnoDB存儲它的表和索引在一個表空間中,表空間能夠包含數個文件。
	核心區別
		MyISAM是非事務安全型的,而InnoDB是事務安全型的。
		MyISAM鎖的粒度是表級,而InnoDB支持行級鎖定。
		MyISAM支持全文類型索引,而InnoDB不支持全文索引。
		MyISAM相對簡單,因此在效率上要優於InnoDB,小型應用能夠考慮使用MyISAM。
		MyISAM表是保存成文件的形式,在跨平臺的數據轉移中使用MyISAM存儲會省去很多的麻煩。
		InnoDB表比MyISAM表更安全,能夠在保證數據不會丟失的狀況下,切換非事務表到事務表(alter table tablename type=innodb)。	
	應用場景
		MyISAM管理非事務表。它提供高速存儲和檢索,以及全文搜索能力。若是應用中須要執行大量的SELECT查詢,那麼MyISAM是更好的選擇。
		InnoDB用於事務處理應用程序,具備衆多特性,包括ACID事務支持。若是應用中須要執行大量的INSERT或UPDATE操做,則應該使用InnoDB,這樣能夠提升多用戶併發操做的性能。		
	Mysql的存儲引擎和索引
		數據庫必須有索引,沒有索引則檢索過程變成了順序查找,O(n)的時間複雜度幾乎是不能忍受的。咱們很是容易想象出一個只有單關鍵字組成的表如何使用B+樹進行索引,只要將關鍵字存儲到樹的節點便可。當數據庫一條記錄裏包含多個字段時,一棵B+樹就只能存儲主鍵,若是檢索的是非主鍵字段,則主鍵索引失去做用,又變成順序查找了。這時應該在第二個要檢索的列上創建第二套索引。 這個索引由獨立的B+樹來組織。有兩種常見的方法能夠解決多個B+樹訪問同一套表數據的問題,一種叫作聚簇索引(clustered index ),一種叫作非聚簇索引(secondary index)。這兩個名字雖然都叫作索引,但這並非一種單獨的索引類型,而是一種數據存儲方式。對於聚簇索引存儲來講,行數據和主鍵B+樹存儲在一塊兒,輔助鍵B+樹只存儲輔助鍵和主鍵,主鍵和非主鍵B+樹幾乎是兩種類型的樹。對於非聚簇索引存儲來講,主鍵B+樹在葉子節點存儲指向真正數據行的指針,而非主鍵。		
		InnoDB使用的是聚簇索引,將主鍵組織到一棵B+樹中,而行數據就儲存在葉子節點上,若使用"where id = 14"這樣的條件查找主鍵,則按照B+樹的檢索算法便可查找到對應的葉節點,以後得到行數據。若對Name列進行條件搜索,則須要兩個步驟:第一步在輔助索引B+樹中檢索Name,到達其葉子節點獲取對應的主鍵。第二步使用主鍵在主索引B+樹種再執行一次B+樹檢索操做,最終到達葉子節點便可獲取整行數據。
		MyISM使用的是非聚簇索引,非聚簇索引的兩棵B+樹看上去沒什麼不一樣,節點的結構徹底一致只是存儲的內容不一樣而已,主鍵索引B+樹的節點存儲了主鍵,輔助鍵索引B+樹存儲了輔助鍵。表數據存儲在獨立的地方,這兩顆B+樹的葉子節點都使用一個地址指向真正的表數據,對於表數據來講,這兩個鍵沒有任何差異。因爲索引樹是獨立的,經過輔助鍵檢索無需訪問主鍵的索引樹。
		爲了更形象說明這兩種索引的區別,咱們假想一個表以下圖存儲了4行數據。其中Id做爲主索引,Name做爲輔助索引。圖示清晰的顯示了聚簇索引和非聚簇索引的差別。
		
		咱們重點關注聚簇索引,看上去聚簇索引的效率明顯要低於非聚簇索引,由於每次使用輔助索引檢索都要通過兩次B+樹查找,這不是畫蛇添足嗎?聚簇索引的優點在哪?
 
咱們重點關注聚簇索引,看上去聚簇索引的效率明顯要低於非聚簇索引,由於每次使用輔助索引檢索都要通過兩次B+樹查找,這不是畫蛇添足嗎?聚簇索引的優點在哪?
			1 因爲行數據和葉子節點存儲在一塊兒,這樣主鍵和行數據是一塊兒被載入內存的,找到葉子節點就能夠馬上將行數據返回了,若是按照主鍵Id來組織數據,得到數據更快。
			2 輔助索引使用主鍵做爲"指針" 而不是使用地址值做爲指針的好處是,減小了當出現行移動或者數據頁分裂時輔助索引的維護工做,使用主鍵值看成指針會讓輔助索引佔用更多的空間,換來的好處是InnoDB在移動行時無須更新輔助索引中的這個"指針"。也就是說行的位置(實現中經過16K的Page來定位,後面會涉及)會隨着數據庫裏數據的修改而發生變化(前面的B+樹節點分裂以及Page的分裂),使用聚簇索引就能夠保證無論這個主鍵B+樹的節點如何變化,輔助索引樹都不受影響。
		因此在百萬級數據及更大數據狀況下,mysql innoDB 的索引表現更加優秀!
五、MySQL性能優化的一些經驗
	a.爲查詢優化你的查詢
		大多數的MySQL服務器都開啓了查詢緩存。這是提升性能最有效的方法之一,並且這是被MySQL的數據庫引擎處理的。當有不少相同的查詢被執行了屢次的時候,這些查詢結果會被放到一個緩存中,這樣,後續的相同的查詢就不用操做表而直接訪問緩存結果了。
		這裏最主要的問題是,對於程序員來講,這個事情是很容易被忽略的。由於,咱們某些查詢語句會讓MySQL不使用緩存。
		請看下面的示例:
			// 查詢緩存不開啓
			$r = mysql_query("SELECT username FROM user WHERE     signup_date >= CURDATE()");
			// 開啓查詢緩存
			$today = date("Y-m-d");
			$r = mysql_query("SELECT username FROM user WHERE signup_date >= '$today'");
		上面兩條SQL語句的差異就是 CURDATE() ,MySQL的查詢緩存對這個函數不起做用。因此,像 NOW() 和 RAND() 或是其它的諸如此類的SQL函數都不會開啓查詢緩存,由於這些函數的返回是會不定的易變的。因此,你所須要的就是用一個變量來代替MySQL的函數,從而開啓緩存。
	b.學會使用EXPLAIN
		使用EXPLAIN關鍵字可讓你知道MySQL是如何處理你的SQL語句的。
			select id, title, cate from news where cate = 1
		發現查詢緩慢,而後在cate字段上增長索引,則會加快查詢
	c.當只要一行數據時使用LIMIT 1
		當你查詢表的有些時候只須要一條數據,請使用 limit 1。
	d.正確的使用索引
		索引並不必定就是給主鍵或是惟一的字段。若是在你的表中,有某個字段你總要會常常用來作搜索、拍下、條件,那麼,請爲其創建索引吧。
	e.不要ORDER BY RAND()
		效率很低的一種隨機查詢。
	f.避免SELECT *
		從數據庫裏讀出越多的數據,那麼查詢就會變得越慢。而且,若是你的數據庫服務器和WEB服務器是兩臺獨立的服務器的話,這還會增長網絡傳輸的負載。必須應該養成一個須要什麼就取什麼的好的習慣。
	g.使用 ENUM 而不是 VARCHAR
		ENUM 類型是很是快和緊湊的。在實際上,其保存的是 TINYINT,但其外表上顯示爲字符串。這樣一來,用這個字段來作一些選項列表變得至關的完美。
		若是你有一個字段,好比「性別」,「國家」,「民族」,「狀態」或「部門」,你知道這些字段的取值是有限並且固定的,那麼,你應該使用 ENUM 而不是 VARCHAR。
	h.使用 NOT NULL
		除非你有一個很特別的緣由去使用 NULL 值,你應該老是讓你的字段保持 NOT NULL。這看起來好像有點爭議,請往下看。
		首先,問問你本身「Empty」和「NULL」有多大的區別(若是是INT,那就是0和NULL)?若是你以爲它們之間沒有什麼區別,那麼你就不要使用NULL。(你知道嗎?在 Oracle 裏,NULL 和 Empty 的字符串是同樣的!)
		不要覺得 NULL 不須要空間,其須要額外的空間,而且,在你進行比較的時候,你的程序會更復雜。 固然,這裏並非說你就不能使用NULL了,現實狀況是很複雜的,依然會有些狀況下,你須要使用NULL值。
		
		下面摘自MySQL本身的文檔
			「NULL columns require additional space in the row to record whether their values are NULL. For MyISAM tables, each NULL column takes one bit extra, rounded up to the nearest byte.」
	i.IP地址存成 UNSIGNED INT
		不少程序員都會建立一個 VARCHAR(15) 字段來存放字符串形式的IP而不是整形的IP。若是你用整形來存放,只須要4個字節,而且你能夠有定長的字段。並且,這會爲你帶來查詢上的優點,尤爲是當你須要使用這樣的WHERE條件:IP between ip1 and ip2。
		咱們必須要使用UNSIGNED INT,由於 IP地址會使用整個32位的無符號整形
	j.固定長度的表會更快
		若是表中的全部字段都是「固定長度」的,整個表會被認爲是 「static」 或 「fixed-length」。 例如,表中沒有以下類型的字段: VARCHAR,TEXT,BLOB。只要你包括了其中一個這些字段,那麼這個表就不是「固定長度靜態表」了,這樣,MySQL 引擎會用另外一種方法來處理。
		固定長度的表會提升性能,由於MySQL搜尋得會更快一些,由於這些固定的長度是很容易計算下一個數據的偏移量的,因此讀取的天然也會很快。而若是字段不是定長的,那麼,每一次要找下一條的話,須要程序找到主鍵。
		而且,固定長度的表也更容易被緩存和重建。不過,惟一的反作用是,固定長度的字段會浪費一些空間,由於定長的字段不管你用不用,他都是要分配那麼多的空間。
	k.垂直分割
		「垂直分割」是一種把數據庫中的表按列變成幾張表的方法,這樣能夠下降表的複雜度和字段的數目,從而達到優化的目的。須要注意的是,這些被分出去的字段所造成的表,你不會常常性地去Join他們,否則的話,這樣的性能會比不分割時還要差,並且,會是極數級的降低。
	l.拆分大的 DELETE 或 INSERT 語句
		若是在一個在線的網站上去執行一個大的 DELETE 或 INSERT 查詢,你須要很是當心,要避免你的操做讓你的整個網站中止相應。由於這兩個操做是會鎖表的,表一鎖住了,別的操做都進不來了。
		Apache 會有不少的子進程或線程。因此,其工做起來至關有效率,而咱們的服務器也不但願有太多的子進程,線程和數據庫連接,這是極大的佔服務器資源的事情,尤爲是內存。
		若是你把你的表鎖上一段時間,好比30秒鐘,那麼對於一個有很高訪問量的站點來講,這30秒所積累的訪問進程/線程,數據庫連接,打開的文件數,可能不只僅會讓你泊WEB服務Crash,還可能會讓你的整臺服務器立刻掛了。
	m.越小的列會越快
		對於大多數的數據庫引擎來講,硬盤操做多是最重大的瓶頸。因此,把你的數據變得緊湊會對這種狀況很是有幫助,由於這減小了對硬盤的訪問。
	n.選擇正確的存儲引擎
		在 MySQL 中有兩個存儲引擎 MyISAM 和 InnoDB,每一個引擎都有利有弊。
		MyISAM 適合於一些須要大量查詢的應用,但其對於有大量寫操做並非很好。甚至你只是須要update一個字段,整個表都會被鎖起來,而別的進程,就算是讀進程都沒法操做直到讀操做完成。另外,MyISAM 對於 SELECT COUNT(*) 這類的計算是超快無比的。
		InnoDB 的趨勢會是一個很是複雜的存儲引擎,對於一些小的應用,它會比 MyISAM 還慢。他是它支持「行鎖」 ,因而在寫操做比較多的時候,會更優秀。而且,他還支持更多的高級應用,好比:事務。

 

 

經測試對一個包含400多萬條記錄的表執行一條件查詢,其查詢時間居然高達40幾秒,相信這麼高的查詢延時,任何用戶都會抓狂。所以如何提升sql語句查詢效率,顯得十分重要。如下是結合網上流傳比較普遍的幾個查詢語句優化方法:mysql

    首先,數據量大的時候,應儘可能避免全表掃描,應考慮在 where及 order by 涉及的列上創建索引,建索引能夠大大加快數據的檢索速度。可是,有些狀況索引是不會起效的:程序員

一、應儘可能避免在 where子句中使用!=或<>操做符,不然將引擎放棄使用索引而進行全表掃描。redis

二、應儘可能避免在 where子句中對字段進行 null值判斷,不然將致使引擎放棄使用索引而進行全表掃描,如:
     select id from t where num is null
     能夠在num上設置默認值0,確保表中num列沒有null值,而後這樣查詢:
     select id from t where num=0算法

三、儘可能避免在 where子句中使用 or來鏈接條件,不然將致使引擎放棄使用索引而進行全表掃描,如:
     select id from t where num=10 or num=20
     能夠這樣查詢:
     select id from t where num=10
     union all
     select id from t where num=20sql

四、下面的查詢也將致使全表掃描:數據庫

    select id from t where name like ‘%abc%’緩存

    若要提升效率,能夠考慮全文檢索。安全

五、in和 not in也要慎用,不然會致使全表掃描,如:
     select id from t where num in(1,2,3)
     對於連續的數值,能用 between就不要用 in了:
     select id from t where num between 1 and 3性能優化

六、若是在 where子句中使用參數,也會致使全表掃描。由於SQL只有在運行時纔會解析局部變量,但優化程序不能將訪問計劃的選擇推遲到運行時;它必須在編譯時進行選擇。然而,若是在編譯時創建訪問計劃,變量的值仍是未知的,於是沒法做爲索引選擇的輸入項。以下面語句將進行全表掃描:
     select id from t where num=@num
     能夠改成強制查詢使用索引:
     select id from t with(index(索引名)) where num=@num服務器

七、應儘可能避免在 where子句中對字段進行表達式操做,這將致使引擎放棄使用索引而進行全表掃描。如:
     select id from t where num/2=100
     應改成:
     select id from t where num=100*2

八、應儘可能避免在where子句中對字段進行函數操做,這將致使引擎放棄使用索引而進行全表掃描。如:
     select id from t where substring(name,1,3)=’abc’–name以abc開頭的id
     select id from t where datediff(day,createdate,’2005-11-30′)=0–’2005-11-30′生成的id
     應改成:
     select id from t where name like ‘abc%’
     select id from t where createdate>=’2005-11-30′ and createdate<’2005-12-1′

九、不要在 where子句中的「=」左邊進行函數、算術運算或其餘表達式運算,不然系統將可能沒法正確使用索引。

十、在使用索引字段做爲條件時,若是該索引是複合索引,那麼必須使用到該索引中的第一個字段做爲條件時才能保證系統使用該索引,不然該索引將不會被使用,而且應儘量的讓字段順序與索引順序相一致。

十一、不要寫一些沒有意義的查詢,如須要生成一個空表結構:
     select col1,col2 into #t from t where 1=0
     這類代碼不會返回任何結果集,可是會消耗系統資源的,應改爲這樣:
     create table #t(…)

十二、不少時候用 exists代替 in是一個好的選擇:
     select num from a where num in(select num from b)
     用下面的語句替換:
     select num from a where exists(select 1 from b where num=a.num)

 

    建索引須要注意的地方:

一、並非全部索引對查詢都有效,SQL是根據表中數據來進行查詢優化的,當索引列有大量數據重複時,SQL查詢可能不會去利用索引,如一表中有字段 sex,male、female幾乎各一半,那麼即便在sex上建了索引也對查詢效率起不了做用。

二、索引並非越多越好,索引當然能夠提升相應的 select的效率,但同時也下降了 insert及 update的效率,由於 insert或 update時有可能會重建索引,因此怎樣建索引須要慎重考慮,視具體狀況而定。一個表的索引數最好不要超過6個,若太多則應考慮一些不常使用到的列上建的索引是否有必要。

三、應儘量的避免更新 clustered索引數據列,由於 clustered索引數據列的順序就是表記錄的物理存儲順序,一旦該列值改變將致使整個表記錄的順序的調整,會耗費至關大的資源。若應用系統須要頻繁更新 clustered索引數據列,那麼須要考慮是否應將該索引建爲 clustered索引。

 

    其餘須要注意的地方:

一、儘可能使用數字型字段,若只含數值信息的字段儘可能不要設計爲字符型,這會下降查詢和鏈接的性能,並會增長存儲開銷。這是由於引擎在處理查詢和鏈接時會逐個比較字符串中每個字符,而對於數字型而言只須要比較一次就夠了。

二、任何地方都不要使用 select * from t,用具體的字段列表代替「*」,不要返回用不到的任何字段。

三、儘可能使用表變量來代替臨時表。若是表變量包含大量數據,請注意索引很是有限(只有主鍵索引)。

四、避免頻繁建立和刪除臨時表,以減小系統表資源的消耗。

五、臨時表並非不可以使用,適當地使用它們可使某些例程更有效,例如,當須要重複引用大型表或經常使用表中的某個數據集時。可是,對於一次性事件,最好使用導出表。

六、在新建臨時表時,若是一次性插入數據量很大,那麼可使用 select into代替 create table,避免形成大量 log,以提升速度;若是數據量不大,爲了緩和系統表的資源,應先create table,而後insert。

七、若是使用到了臨時表,在存儲過程的最後務必將全部的臨時表顯式刪除,先 truncate table,而後 drop table,這樣能夠避免系統表的較長時間鎖定。

八、儘可能避免使用遊標,由於遊標的效率較差,若是遊標操做的數據超過1萬行,那麼就應該考慮改寫。

九、使用基於遊標的方法或臨時表方法以前,應先尋找基於集的解決方案來解決問題,基於集的方法一般更有效。

十、與臨時表同樣,遊標並非不可以使用。對小型數據集使用 FAST_FORWARD 遊標一般要優於其餘逐行處理方法,尤爲是在必須引用幾個表才能得到所需的數據時。在結果集中包括「合計」的例程一般要比使用遊標執行的速度快。若是開發時間容許,基於遊標的方法和基於集的方法均可以嘗試一下,看哪種方法的效果更好。

十一、在全部的存儲過程和觸發器的開始處設置 SET NOCOUNT ON,在結束時設置 SET NOCOUNT OFF。無需在執行存儲過程和觸發器的每一個語句後向客戶端發送 DONE_IN_PROC消息。

十二、儘可能避免向客戶端返回大數據量,若數據量過大,應該考慮相應需求是否合理。

1三、儘可能避免大事務操做,提升系統併發能力。

 

總結

# 第一優化你的sql和索引; # 第二加緩存,memcached,redis; # 第三以上都作了後,仍是慢,就作主從複製或主主複製,讀寫分離,
 能夠在應用層作,效率高,也能夠用三方工具,第三方工具推薦360的atlas,其它的要麼效率不高,要麼沒人維護; # 第四若是以上都作了仍是慢,不要想着去作切分,
 mysql自帶分區表,先試試這個,對你的應用是透明的,無需更改代碼,可是sql語句是須要針對分區表作優化的,sql條件中要帶上分區條件的列,從而使查詢定位到少許的分區上,
不然就會掃描所有分區,另外分區表還有一些坑,在這裏就很少說了;
# 第五若是以上都作了,那就先作垂直拆分, 其實就是根據你模塊的耦合度,將一個大的系統分爲多個小的系統,也就是分佈式系統; # 第六纔是水平切分, 針對數據量大的表,這一步最麻煩,最能考驗技術水平,要選擇一個合理的sharding key,爲了有好的查詢效率,表結構也要改動,作必定的冗餘,應用也要改,sql中儘可能帶sharding key,
將數據定位到限定的表上去查,而不是掃描所有的表;
# mysql數據庫通常都是按照這個步驟去演化的,成本也是由低到高。

1

相關文章
相關標籤/搜索