Mysql分區

                                                                               Mysql分區

1、什麼是mysql分區

    

使用myisam引擎的一張表主要對應着三個文件,一個是frm存放表結構的,一個是myd存放表數據的,一個是myi存表索引的。如果一張表的數據量太大的話,那麼myd,myi就會變的很大,查找數據就會變的很慢,這個時候我們可以利用mysql的分區功能,在物理上將這一張表對應的三個文件,分割成許多個小塊,這樣呢,我們查找一條數據時,就不用全部查找了,只要知道這條數據在哪一塊,然後在那一塊找就行了。如果表的數據太大,可能一個磁盤放不下,這個時候,我們可以把數據分配到不同的磁盤裏面去。
使用innoDB引擎的/mysql/data/數據庫名目錄下一張表有一個frm文件存放數據結構,其他的數據部分全部都存在在/mysql/data目錄下的ibdata文件中。

2、mysql分區的有點和缺點

 

MySQL分區帶來的好處太多了,這裏強調兩點好處:

性能的提升(Increased performance) - 在掃描操作中,如果MySQL的優化器知道哪個分區中才包含特定查詢中需要的數據,它就能直接去掃描那些分區的數據,而不用浪費很多時間掃描不需要的地方 了。需要舉個例子?好啊,百萬行的表劃分爲10個分區,每個分區就包含十萬行數據,那麼查詢分區需要的時間僅僅是全表掃描的十分之一了,很明顯的對比。同 時對十萬行的表建立索引的速度也會比百萬行的快得多得多。如果你能把這些分區建立在不同的磁盤上,這時候的I/O讀寫速度就“不堪設想”(沒用錯詞,真的 太快了,理論上100倍的速度提升啊,這是多麼快的響應速度啊,所以有點不堪設想了)了。

對數據管理的簡化(Simplified data management) - MySQL分區技術可以讓DBA對數據的管理能力提升。通過優良的MySQL分區,DBA可以簡化特定數據操作的執行方式。例如:DBA在對某些分區的內容進行刪除的同時能保證餘下的分區的數據完整性(這是跟對錶的數據刪除這種大動作做比較的)。 此外分區是由MySQL系統直接管理的,DBA不需要手工的去劃分和維護。

在下面的場景中,分區可以起到非常大的作用:

A:表非常大以至於無法全部都放在內存中,或者只在表的最後部分有熱點數據,其他都是歷史數據

B:分區表的數據更容易維護,如:想批量刪除大量數據可以使用清除整個分區的方式。另外,還可以對一個獨立分區進行優化、檢查、修復等操作

C:分區表的數據可以分佈在不同的物理設備上,從而高效地利用多個硬件設備

D:可以使用分區表來避免某些特殊的瓶頸,如:innodb的單個索引的互斥訪問,ext3文件系統的inode鎖競爭等

E:如果需要,還可以備份和恢復獨立的分區,這在非常大的數據集的場景下效果非常好

F:優化查詢,在where字句中包含分區列時,可以只使用必要的分區來提高查詢效率,同時在涉及sum()和count()這類聚合函數的查詢時,可以在每個分區上面並行處理,最終只需要彙總所有分區得到的結果。

分區本身也有一些限制:

A:一個表最多只能有1024個分區(mysql5.6之後支持8192個分區)

B:在mysql5.1中分區表達式必須是整數,或者是返回整數的表達式,在5.5之後,某些場景可以直接使用字符串列和日期類型列來進行分區(使用varchar字符串類型列時,一般還是字符串的日期作爲分區)。

C:如果分區字段中有主鍵或者唯一索引列,那麼所有主鍵列和唯一索引列都必須包含進來,如果表中有主鍵或唯一索引,那麼分區鍵必須是主鍵或唯一索引

D:分區表中無法使用外鍵約束

E:mysql數據庫支持的分區類型爲水平分區,並不支持垂直分區,因此,mysql數據庫的分區中索引是局部分區索引,一個分區中既存放了數據又存放了索引,而全局分區是指的數據庫放在各個分區中,但是所有的數據的索引放在另外一個對象中

F:目前mysql不支持空間類型和臨時表類型進行分區。不支持全文索引



3、mysql分區的幾種方式

1,range分區
按照RANGE分區的表是通過如下一種方式進行分區的,每個分區包含那些分區表達式的值位於一個給定的連續區間內的行。
2,list分區
LIST分區中每個分區的定義和選擇是基於某列的值從屬於一個值列表集中的一個值,而RANGE分 區是從屬於一個連續區間值的集合。
3,hash分區
HASH分區主要用來確保數據在預先確定數目的分區中平均分佈,你所要做的只是基於將要被哈希的列值指定一個列值或表達式,以 及指定被分區的表將要被分割成的分區數量。
4,key分區
按照KEY進行分區類似於按照HASH分區,除了HASH分區使用的用 戶定義的表達式,而KEY分區的 哈希函數是由MySQL 服務器提供。
5,子分區
子分區是分區表中每個分區的再次分割,子分區既可以使用HASH希分區,也可以使用KEY分區。這 也被稱爲複合分區(composite partitioning)。


4、mysql分區與水平分表的區別



5、mysql分區的具體實現

RANGE 

分區:基於屬於一個給定連續區間的列值,把多行分配給分區。

RANGE 

分區:基於屬於一個給定連續區間的列值,把多行分配給分區。

RANGE 

分區:基於屬於一個給定連續區間的列值,把多行分配給分區。

RANGE 

分區:基於屬於一個給定連續區間的列值,把多行分配給分區。

RANGE 

分區:基於屬於一個給定連續區間的列值,把多行分配給分區。

RANGE 

分區:基於屬於一個給定連續區間的列值,把多行分配給分區。

RANGE 

分區:基於


RANGE 分區:基於屬於一個給定連續區間的列值,把多行分配給分區。

複製代碼代碼如下:

DROP TABLE IF EXISTS `p_range`;
CREATE TABLE `p_range` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`name` char(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=9 DEFAULT CHARSET=utf8
/*!50100 PARTITION BY RANGE (id)
(PARTITION p0 VALUES LESS THAN (8) ENGINE = MyISAM) */;

range分區就是 partition by range(id) 表示按id 1-7的數據存儲在p0分區;如果id大於7了則數據不能寫入了,因爲沒有對應的數據分區來存儲;
所以這時在創建分區時需要使用maxvalues關鍵字了
複製代碼代碼如下:

PARTITION BY RANGE (id)
(
PARTITION p0 VALUES LESS THAN (8),
PARTITION p1 VALUES LESS THAN MAXVALUE)

這樣就表示,所有id大於7的數據記錄存在在p1分區裏。
RANGE分區在如下場合特別有用:
·  當需要刪除“舊的”數據時。如果你使用上面最近的那個例子給出的分區方案,你只需簡單地使用 “ALTER TABLE employees DROP PARTITION p0;”來刪除所有在1991年前就已經停止工作的僱員相對應的所有行。對於有大量行的表,這比運行一個如“DELETE FROM employees WHERE YEAR(separated) <= 1990;”這樣的一個DELETE查詢要有效得多。
·  想要使用一個包含有日期或時間值,或包含有從一些其他級數開始增長的值的列。
·  經常運行直接依賴於用於分割表的列的查詢。例如,當執行一個如“SELECT COUNT(*) FROM employees WHERE YEAR(separated) = 2000 GROUP BY store_id;”這樣的查詢時,MySQL可以很迅速地確定只有分區p2需要掃描,這是因爲餘下的分區不可能包含有符合該WHERE子句的任何記錄。
LIST 分區:類似於按RANGE分區,區別在於LIST分區是基於列值匹配一個離散值集合中的某個值來進行選擇。
list分區可以理解爲按一個鍵的id區間進行數據存儲,比如類型表 1,2,3,4的所有記錄存儲在p0裏面,5,6,7,8存在在p1分區裏面
這裏與range分區一樣,如果現在有條記錄typeid是9,那麼這條記錄是不能存入的;
需要注意的是:LIST分區沒有類似如“VALUES LESS THAN MAXVALUE”這樣的包含其他值在內的定義。將要匹配的任何值都必須在值列表中找到。
複製代碼代碼如下:

DROP TABLE IF EXISTS `p_list`;
CREATE TABLE `p_list` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`typeid` mediumint(10) NOT NULL DEFAULT '0',
`typename` char(20) DEFAULT NULL,
PRIMARY KEY (`id`,`typeid`)
) ENGINE=MyISAM AUTO_INCREMENT=9 DEFAULT CHARSET=utf8
/*!50100 PARTITION BY LIST (typeid)
(PARTITION p0 VALUES IN (1,2,3,4) ENGINE = MyISAM,
PARTITION p1 VALUES IN (5,6,7,8) ENGINE = MyISAM) */;

HASH分區:基於用戶定義的表達式的返回值來進行選擇的分區,該表達式使用將要插入到表中的這些行的列值進行計算。這個函數可以包含MySQL 中有效的、產生非負整數值的任何表達式。
HASH分區主要用來確保數據在預先確定數目的分區中平均分佈。在RANGE和LIST分區中,必須明確指定一個給定的列值或列值集合應該保存在哪個分區中;而在HASH分區中,MySQL 自動完成這些工作,你所要做的只是基於將要被哈希的列值指定一個列值或表達式,以及指定被分區的表將要被分割成的分區數量。
要使用HASH分區來分割一個表,要在CREATE TABLE 語句上添加一個“PARTITION BY HASH (expr)”子句,其中“expr”是一個返回一個整數的表達式。它可以僅僅是字段類型爲MySQL 整型的一列的名字。此外,你很可能需要在後面再添加一個“PARTITIONS num”子句,其中num 是一個非負的整數,它表示表將要被分割成分區的數量。如果沒有包括一個PARTITIONS子句,那麼分區的數量將默認爲1。
複製代碼代碼如下:

DROP TABLE IF EXISTS `p_hash`;
CREATE TABLE `p_hash` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`storeid` mediumint(10) NOT NULL DEFAULT '0',
`storename` char(255) DEFAULT NULL,
PRIMARY KEY (`id`,`storeid`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8
/*!50100 PARTITION BY HASH (storeid)
PARTITIONS 4 */;

InnoDB引擎
簡單點說就是數據的存入可以按 partition by hash(expr); 這裏的expr可以是鍵名也可以是表達式比如YEAR(time),如果是表達式的情況下
“但是應當記住,每當插入或更新(或者可能刪除)一行,這個表達式都要計算一次;這意味着非常複雜的表達式可能會引起性能問題,尤其是在執行同時影響大量行的運算(例如批量插入)的時候。 ”
在執行刪除、寫入、更新時這個表達式都會計算一次。
數據的分佈採用基於用戶函數結果的模數來確定使用哪個編號的分區。換句話,對於一個表達式“expr”,將要保存記錄的分區編號爲N ,其中“N = MOD(expr, num)”。
比如上面的storeid 爲10;那麼 N=MOD(10,4) ;N是等於2的,那麼這條記錄就存儲在p2的分區裏面。
如果插入一個表達式列值爲'2005-09-15′的記錄到表中,那麼保存該條記錄的分區確定如下:MOD(YEAR('2005-09-01′),4)  =  MOD(2005,4)  =  1 ;就存儲在p1分區裏面了。
“MySQL 5.1 還支持一個被稱爲“linear hashing(線性哈希功能)”的變量,它使用一個更加複雜的算法來確定新行插入到已經分區了的表中的位置。
線性哈希分區和常規哈希分區在語法上的唯一區別在於,在“PARTITION BY” 子句中添加“LINEAR”關鍵字;線性哈希功能使用的一個線性的2的冪(powers-of-two)運算法則
按照線性哈希分區的優點在於增加、刪除、合併和拆分分區將變得更加快捷,有利於處理含有極其大量(1000GB)數據的表。
它的缺點在於,與使用常規HASH分區得到的數據分佈相比,各個分區間數據的分佈不大可能均衡。”
KEY 分區:類似於按HASH分區,區別在於KEY分區只支持計算一列或多列,且MySQL 服務器提供其自身的哈希函數。必須有一列或多列包含整數值。
複製代碼代碼如下:

DROP TABLE IF EXISTS `p_key`;
CREATE TABLE `p_key` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`keyname` char(20) DEFAULT NULL,
`keyval` varchar(1000) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=12 DEFAULT CHARSET=utf8
/*!50100 PARTITION BY KEY (id)
PARTITIONS 4 */;

按照KEY進行分區類似於按照HASH分區,除了HASH分區使用的用戶定義的表達式,而KEY分區的 哈希函數是由MySQL 服務器提供。MySQL 簇(Cluster)使用函數MD5()來實現KEY分區;對於使用其他存儲引擎的表,服務器使用其自己內部的 哈希函數,這些函數是基於與PASSWORD()一樣的運算法則。
“CREATE TABLE … PARTITION BY KEY”的語法規則類似於創建一個通過HASH分區的表的規則。它們唯一的區別在於使用的關鍵字是KEY而不是HASH,並且KEY分區只採用一個或多個列名的一個列表。
與hash的區別就是,hash使用用戶定義的表達式如YEAR(time) ;而key分區則是由mysql服務器提供的。同樣KEY也是可以使用linear線性key的,與hash linear是相同的算法。
子分區:是分區表中每個分區的再次分割。
複製代碼代碼如下:

DROP TABLE IF EXISTS `p_subpartition`;
CREATE TABLE `p_subpartition` (
`id` int(10) DEFAULT NULL,
`title` char(255) NOT NULL,
`createtime` date NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8
/*!50100
PARTITION BY RANGE (YEAR(createtime))
SUBPARTITION BY HASH (MONTH(createtime))
(PARTITION p0 VALUES LESS THAN (2012)
(SUBPARTITION s1 ENGINE = MyISAM,
SUBPARTITION s2 ENGINE = MyISAM),
PARTITION p1 VALUES LESS THAN (2013)
(SUBPARTITION s3 ENGINE = MyISAM,
SUBPARTITION s4 ENGINE = MyISAM),
PARTITION p2 VALUES LESS THAN MAXVALUE
(SUBPARTITION s5 ENGINE = MyISAM,
SUBPARTITION s6 ENGINE = MyISAM)) */;

可以看到p_subpartition有三個分區p0,p1,p2;而這三個分區每一個又進一步分爲2個分區。那麼整個表都就分爲6個小分區;

可以看到代表p_sobpartitionp0.myd的文件消失了,取代的是p_subpartition#p#p0#sp#s1.myd
在MySQL 5.1中,對於已經通過RANGE或LIST分區了的表再進行子分區是可能的。
子分區是分區表中每個分區的再次分割,子分區既可以使用HASH希分區,也可以使用KEY分區。這 也被稱爲複合分區(composite partitioning)。
1,如果一個分區中創建了子分區,其他分區也要有子分區
2,如果創建了了分區,每個分區中的子分區數必有相同
3,同一分區內的子分區,名字不相同,不同分區內的子分區名子可以相同(5.1.50不適用)
分區注意點
1、重新分區時,如果原分區裏面存在maxvalue則新的分區裏面也必須包含maxvalue否則就錯誤。
alter table p_range2x
reorganize partition p1,p2
into (partition p0 values less than (5), partition p1 values less than maxvalue);
[Err] 1520 – Reorganize of range partitions cannot change total ranges except for last partition where it can extend the range
2、分區刪除時,數據也同樣會被刪除
alter table p_range drop partition p0;
3、如果range分區列表裏面沒有maxvalue則如有新數據大於現在分區range數據值那麼這個數據是無法寫入到數據庫表的。
4、修改表名不需要 刪除分區後在進行更改,修改表名後分區存儲myd myi對應也會自動更改。
如果希望從所有分區刪除所有的數據,但是又保留表的定義和表的分區模式,使用TRUNCATE TABLE命令。(請參見13.2.9節,“TRUNCATE語法”)。
如果希望改變表的分區而又不丟失數據,使用“ALTER TABLE … REORGANIZE PARTITION”語句。參見下面的內容,或者在13.1.2節,“ALTER TABLE語法” 中參考關於REORGANIZE PARTITION的信息。
5、對錶進行分區時,不論採用哪種分區方式如果表中存在主鍵那麼主鍵必須在分區列中。表分區的侷限性。
6、list方式分區沒有類似於range那種 less than maxvalue的寫法,也就是說list分區表的所有數據都必須在分區字段的值列表集合中。
7、在MySQL 5.1版中,同一個分區表的所有分區必須使用同一個存儲引擎;例如,不能對一個分區使用MyISAM,而對另一個使用InnoDB。
8、分區的名字是不區分大小寫的,myp1與MYp1是相同的。
分區的管理
range與list分區的改變動作不能適用於hash與key方式的分區。刪除與添加動作是都能使用的。
以下面的例子
複製代碼代碼如下:

DROP TABLE IF EXISTS `p_list`;
CREATE TABLE `p_list` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`typeid` mediumint(10) NOT NULL DEFAULT '0',
`typename` char(20) DEFAULT NULL,
PRIMARY KEY (`id`,`typeid`)
) ENGINE=MyISAM AUTO_INCREMENT=9 DEFAULT CHARSET=utf8
/*!50100 PARTITION BY LIST (typeid)
(PARTITION p0 VALUES IN (1,2,3,4) ENGINE = MyISAM,
PARTITION p1 VALUES IN (5,6,7,8) ENGINE = MyISAM) */;


range與list分區的管理
刪除分區
ALTER TABLE tr DROP PARTITION p1;
需要注意的是刪除分區後,該分區的所有數據都沒有了。同時刪除後存在一個重大影響也就是typeid爲5,6,7,8的記錄是不能寫入到該表了的!
清空數據
如果想要保留表結構與分區結構可以使用 TRUNCATE TABLE 清空表
更改分區保留數據
ALTER TABLE tbl_name REORGANIZE PARTITION partition_list INTO (partition_definitions);如果想保留數據進行分區的更改
ALTER TABLE p_list REORGANIZE PARTITION p0 INTO (
 PARTITION s0 VALUES IN(1,2),
 PARTITION s1 VALUES IN(3,4),
);這樣就能進行分區的合併了,那怎麼進行拆分呢
ALTER TABLE p_list REORGANIZE PARTITION s0,s1 INTO (
 PARTITION p0 VALUES IN(1,2,3,4),
); 使用 REORGANIZE PARTITION進行數據的合併與拆分,數據是沒有丟失的。
在使用REORGANIZE進行重新分區時,需要注意幾點:
1、用來確定新分區模式的PARTITION子句使用與用在CREATE TABLE中確定分區模式的PARTITION子句相同的規則。(partition 分區子句必須與創建原分區時的規則相同)
2、partition_definitions 列表中分區的合集應該與在partition_list 中命名分區的合集佔有相同的區間或值集合。 (不管是合併還是拆分,s0,s1到p0;p0到s0,s1 裏面的區間或者值都必須相同)
3、對於按照RANGE分區的表,只能重新組織相鄰的分區;不能跳過RANGE分區。(比如按range年份 p0 1990,p1 2000 ,p2 2013三個分區;在合併時partition p0,p2 into()
   這樣是不行的,因爲這兩個分區不是相鄰的分區;)
4、不能使用REORGANIZE PARTITION來改變表的分區類型;也就是說,例如,不能把RANGE分區變爲HASH分區,反之亦然。也不能使用該命令來改變分區表達式或列。
增加分區
ALTER TABLE p_list ADD PARTITION (PARTITION p2 VALUES IN (9, 10, 11));
但是不能使用
ALTER TABLE p_list ADD PARTITION (PARTITION p2 VALUES IN (9, 14));
這樣mysql 會產生錯誤1465 (HY000): 在LIST分區中,同一個常數的多次定義
hash與key分區的管理在改變分區設置方面,按照HASH分區或KEY分區的表彼此非常相似,但是它們又與按照RANGE或LIST分區的表在很多方面有差別。
關於添加和刪除按照RANGE或LIST進行分區的表的分區
不能使用與從按照RANGE或LIST分區的表中刪除分區相同的方式,來從HASH或KEY分區的表中刪除分區。但是,可以使用“ALTER TABLE ... COALESCE PARTITION”命令來合併HASH或KEY分區。
查看源代碼打印幫助1 DROP TABLE IF EXISTS `p_hash`;  2    3 CREATE TABLE `p_hash` (  4 `id` int(10) NOT NULL AUTO_INCREMENT,  5 `storeid` mediumint(10) NOT NULL DEFAULT '0',  6 `storename` char(255) DEFAULT NULL,  7 PRIMARY KEY (`id`,`storeid`)  8 ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8  9 /*!50100 PARTITION BY HASH (storeid)  10 PARTITIONS 4 */; 
如p_hash的分區數爲4個;
要減少分區數爲2個
ALTER TABLE p_hash COALESCE PARTITION 2;
對於按照HASH,KEY,LINEAR HASH,或LINEAR KEY分區的表, COALESCE能起到同樣的作用。COALESCE不能用來增加分區的數量,如果你嘗試這麼做,結果會出現類似於下面的錯誤:
mysql> ALTER TABLE clients COALESCE PARTITION 18;
錯誤1478 (HY000): 不能移動所有分區,使用DROP TABLE代替要增加顧客表的分區數量從12到18,使用“ALTER TABLE … ADD PARTITION”,具體如下:
ALTER TABLE clients ADD PARTITION PARTITIONS 18;註釋:“ALTER TABLE … REORGANIZE PARTITION”不能用於按照HASH或HASH分區的表。
分區維護
重建分區
這和先刪除保存在分區中的所有記錄,然後重新插入它們,具有同樣的效果。它可用於整理分區碎片。
ALTER TABLE t1 REBUILD PARTITION (p0, p1);
優化分區如果從分區中刪除了大量的行,或者對一個帶有可變長度的行(也就是說,有VARCHAR,BLOB,或TEXT類型的列)作了許多修改,
可以使用“ALTER TABLE … OPTIMIZE PARTITION”來收回沒有使用的空間,並整理分區數據文件的碎片。
ALTER TABLE t1 OPTIMIZE PARTITION (p0, p1);
分析分區
讀取並保存分區的鍵分佈
ALTER TABLE t1 ANALYZE PARTITION (p3);
修補分區: 修補被破壞的分區。
ALTER TABLE t1 REPAIR PARTITION (p0,p1);
檢查分區
可以使用幾乎與對非分區表使用CHECK TABLE 相同的方式檢查分區。
ALTER TABLE trb3 CHECK PARTITION (p1);
這個命令可以告訴你表t1的分區p1中的數據或索引是否已經被破壞。如果發生了這種情況,使用“ALTER TABLE ... REPAIR PARTITION”來修補該分區。獲取分區信息
在mysql服務器信息數據庫裏面的partitions存放着服務器所有表的分區信息。
複製代碼代碼如下:

explain partitions命令
explain partitions select * from p_hash
+----+-------------+--------+-------------+------+---------------+------+---------+------+------+-------+
| id | select_type | table  | partitions  | type | possible_keys | key  | key_len | ref  | rows | Extra |
+----+-------------+--------+-------------+------+---------------+------+---------+------+------+-------+
|  1 | SIMPLE    | p_hash | p0,p1,p2,p3 | ALL  | NULL      | NULL | NULL   | NULL |  10 |    |
+----+-------------+--------+-------------+------+---------------+------+---------+------+------+-------+

-- 獲取到p_list表的分區詳細信息。
select * from information_schema.`PARTITIONS` where TABLE_NAME = 'p_list';
-- 分區的創建信息
show create table p_list;

DROP 

TABLE 

IF 

EXISTS 

`p_range`; 

CREATE 

TABLE 

`p_range` 

`id` 

int(10) 

NOT 

NULL 

AUTO_INCREMENT, 

`name` 

char(20) 

NOT 

NULL, 

PRIMARY 

KEY 

(`id`) 

ENGINE=MyISAM 

AUTO_INCREMENT=9 

DEFAULT 

CHARSET=utf8 

/*!50100 

PARTITION 

BY 

RANGE 

(id) 

(PARTITION 

p0 

VALUES 

LESS 

THAN 

(8) 

ENGINE 

MyISAM)








































 







發佈了20 篇原創文章 · 獲贊 10 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章