mysql優(yōu)化學習

1.高并發(fā)優(yōu)化點有:

如果請求過多,判定web服務器的壓力過大,增加前端的web服務器,做負載均衡

如果請求靜態(tài)界面不卡了,但是動態(tài)數(shù)據(jù)還是卡,說明MySQL處理的請求太多了,在應用層增加緩存.

數(shù)據(jù)庫層其實是最脆弱的一層,一般在應用設計時在上游就需要把請求攔截掉,數(shù)據(jù)庫層只承擔“能力范圍內(nèi)”的訪問請求,所以,我們通過在服務層引入隊列和緩存,讓最底層的數(shù)據(jù)庫高枕無憂。但是如果請求激增,還是有大量的查詢壓力到MySQL,這個時候就要想辦法解決MySQL的瓶頸了。

2.mysql執(zhí)行流程:

大致可以分為以下步驟:

1.當我們請求mysql服務器的時候,MySQL前端會有一個監(jiān)聽,請求到了之后,服務器得到相關的SQL語句,執(zhí)行之前(虛線部分為執(zhí)行),還會做權限的判斷

2.通過權限之后,SQL就到MySQL內(nèi)部,他會在查詢緩存中,看該SQL有沒有執(zhí)行過,如果有查詢過,則把緩存結果返回,說明在MySQL內(nèi)部,也有一個查詢緩存.但是這個查詢緩存,默認是不開啟的,這個查詢緩存,和我們的Hibernate,Mybatis的查詢緩存是一樣的,因為查詢緩存要求SQL和參數(shù)都要一樣,所以這個命中率是非常低的。

3.如果我們沒有開啟查詢緩存,或者緩存中沒有找到對應的結果,那么就到了解析器,解析器主要對SQL語法進行解析

4.解析結束后就變成一顆解析樹,這個解析樹其實在Hibernate里面也是有的,大家回憶一下,在以前做過Hibernate項目的時候,是不是有個一個antlr.jar。這個就是專門做語法解析的工具.因為在Hibernate里面有HQL,它就是通過這個工具轉換成SQL的,我們編程語言之所以有很多規(guī)范、語法,其實就是為了便于這個解析器解析,這個學過編譯原理的應該知道.

5.得到解析樹之后,不能馬上執(zhí)行,這還需要對這棵樹進行預處理,也就是說,這棵樹,我沒有經(jīng)過任何優(yōu)化的樹,預處理器會這這棵樹進行一些預處理,比如常量放在什么地方,如果有計算的東西,把計算的結果算出來等等...

6.預處理完畢之后,此時得到一棵比較規(guī)范的樹,這棵樹就是要拿去馬上做執(zhí)行的樹,比起之前的那棵樹,這棵得到了一些優(yōu)化的解析樹

7.查詢優(yōu)化器,是MySQL里面最關鍵的東西,我們寫任何一條SQL,比如SELECT * FROM USER WHERE USERNAME = toby AND PASSWORD = 1,它會怎么去執(zhí)行?它是先執(zhí)行username = toby還是password = 1?每一條SQL的執(zhí)行順序查詢優(yōu)化器就是根據(jù)MySQL對數(shù)據(jù)統(tǒng)計表的一些信息,比如索引,比如表一共有多少數(shù)據(jù),MySQL都是有緩存起來的,在真正執(zhí)行SQL之前,他會根據(jù)自己的這些數(shù)據(jù),進行一個綜合的判定,判斷這一次在多種執(zhí)行方式里面,到底選哪一種執(zhí)行方式,可能運行的最快.這一步是MySQL性能中,最關鍵的核心點,也是我們的優(yōu)化原則.我們平時所講的優(yōu)化SQL,其實說白了,就是想讓查詢優(yōu)化器,按照我們的想法,幫我們選擇最優(yōu)的執(zhí)行方案,因為我們比MySQL更懂我們的數(shù)據(jù).MySQL看數(shù)據(jù),僅僅只是自己收集到的信息,這些信息可能是不準確的,MySQL根據(jù)這些信息選了一個它自認為最優(yōu)的方案,但是這個方案可能和我們想象的不一樣.

8.這里的查詢執(zhí)行計劃,也就是MySQL查詢中的執(zhí)行計劃,比如要先執(zhí)行username = toby還是password = 1

9.這個執(zhí)行計劃會傳給查詢執(zhí)行引擎,執(zhí)行引擎選擇存儲引擎來執(zhí)行這一份傳過來的計劃,到磁盤中的文件中去查詢,這個時候重點來了,影響這個查詢性能最根本的原因是什么?就是硬盤的機械運動,也就是我們平時熟悉的IO,所以一條查詢語句是快還是慢,就是根據(jù)這個時間的IO來確定的.那怎么執(zhí)行IO又是什么來確定的?就是傳過來的這一份執(zhí)行計劃.

10.如果開了查詢緩存,則返回結果給客戶端,并且查詢緩存也放一份。



#要提高MySQL的更新/插入效率,應首先考慮降低鎖的競爭,減少寫操作的等待時間

3.增刪改查

一、INSERT語句:

基本:INSERT [INTO] 表名 [(字段列表)] VALUES (值列表)[, (值列表), …]

注意:

如果要插入的值列表包含所有字段并且順序一致,則可以省略字段列表。

可同時插入多條數(shù)據(jù)記錄!

REPLACE 與 INSERT 完全一樣,可互換。

優(yōu)化前例子:

優(yōu)化策略:

(1)當我們需要批量插入數(shù)據(jù)的時候,這樣的語句卻會出現(xiàn)性能問題。例如說,如果有需要插入100000條數(shù)據(jù),那么就需要有100000條insert語句,每一句都需要提交到關系引擎那里去解析,優(yōu)化,然后才能夠到達存儲引擎做真的插入工作。上述所說的同時插入多條就是一種優(yōu)化。(經(jīng)測試,大概10條同時插入是最高效的)

優(yōu)化后例子:

(2)將進程/線程數(shù)控制在2倍于CPU數(shù)目相對合適

(3)采用順序主鍵策略(例如自增主鍵,或者修改業(yè)務邏輯,讓插入的記錄盡可能順序主鍵)

(4)考慮使用replace 語句代替insert語句。(REPLACE語句請參考下文,有詳細講述)

二、DELETE語句:

DELETE FROM 表名[ 刪除條件子句](沒有條件子句,則會刪除全部)

例子:

補充:Mysql中的truncate table和delete語句都可以刪除表里面所有數(shù)據(jù),但是在一些情況下有些不同!

例子:

truncate table gag;

(1)truncate table刪除速度更快,,但truncate table刪除后不記錄mysql日志,不可以恢復數(shù)據(jù)。(謹慎使用)

(2)如果沒有外鍵關聯(lián),innodb執(zhí)行truncate是先drop table(原始表),再創(chuàng)建一個跟原始表一樣空表,速度要遠遠快于delete逐條刪除行記錄。

(3)如果使用innodb_file_per_table參數(shù),truncate table 能重新利用釋放的硬盤空間,在InnoDB Plugin中,truncate table為自動回收,如果不是用InnoDB Plugin,那么需要使用optimize table來優(yōu)化表,釋放空間。

truncate table刪除表后,optimize table尤其重要,特別是大數(shù)據(jù)數(shù)據(jù)庫,表空間可以得到釋放!

(4)表有外鍵關聯(lián),truncate table刪除表數(shù)據(jù)為逐行刪除,如果外鍵指定級聯(lián)刪除(delete cascade),關聯(lián)的子表也會會被刪除所有表數(shù)據(jù)。如果外鍵未指定級聯(lián)(cascde),truncate table逐行刪除數(shù)據(jù),如果是父行關聯(lián)子表行數(shù)據(jù),將會報錯。

注意:

一個大的 DELETE 或 INSERT 操作,要非常小心,因為這兩個操作是會鎖表的,表一鎖住,其他操作就進不來了。因此,我們要交給DBA去拆分,重整數(shù)據(jù)庫策略,比如限制處理1000條。

另外,擴展下刪除和索引的聯(lián)系,由于索引需要額外的維護成本;因為索引文件是單獨存在的文件,所以當我們對數(shù)據(jù)的增加,修改,刪除,都會產(chǎn)生額外的對索引文件的操作,這些操作需要消耗額外的IO,會降低增/改/刪的執(zhí)行效率。所以,在我們刪除數(shù)據(jù)庫百萬級別數(shù)據(jù)的時候,查詢MySQL官方手冊得知刪除數(shù)據(jù)的速度和創(chuàng)建的索引數(shù)量是成正比的。所以我們想要刪除百萬數(shù)據(jù)的時候可以先刪除索引(此時大概耗時三分多鐘),然后刪除其中無用數(shù)據(jù),此過程需要不到兩分鐘,刪除完成后重新創(chuàng)建索引(此時數(shù)據(jù)較少了)創(chuàng)建索引也非???,約十分鐘左右。與之前的直接刪除絕對是要快速很多,更別說萬一刪除中斷,一切刪除會回滾。那更是坑了。

三、UPDATE語句:

UPDATE 表名 SET 字段名=新值[, 字段名=新值] [更新條件]

例子:

優(yōu)化:更新多條記錄(往后會結合MyBatics寫個實例)

更新多條記錄的多個值

(1). 盡量不要修改主鍵字段。(廢話,反正我就從沒改過..)

(2). 當修改VARCHAR型字段時,盡量使用相同長度內(nèi)容的值代替。

(3). 盡量最小化對于含有UPDATE觸發(fā)器的表的UPDATE操作。

(4). 避免UPDATE將要復制到其他數(shù)據(jù)庫的列。

(5). 避免UPDATE建有很多索引的列。

(6). 避免UPDATE在WHERE子句條件中的列。

四、REPLACE語句:

根據(jù)應用情況可以使用replace 語句代替insert/update語句。例如:如果一個表在一個字段上建立了唯一索引,當向這個表中使用已經(jīng)存在的鍵值插入一條記錄,將會拋出一個主鍵沖突的錯誤。如果我們想用新記錄的值來覆蓋原來的記錄值時,就可以使用REPLACE語句。

使用REPLACE插入記錄時,如果記錄不重復(或往表里插新記錄),REPLACE功能與INSERT一樣,如果存在重復記錄,REPLACE就使用新記錄的值來替換原來的記錄值。使用REPLACE的最大好處就是可以將DELETE和INSERT合二為一,形成一個原子操作。這樣就可以不必考慮同時使用DELETE和INSERT時添加事務等復雜操作了。

在使用REPLACE時,表中必須有唯一有一個PRIMARY KEY或UNIQUE索引,否則,使用一個REPLACE語句沒有意義。

用法:

(1)同INSERT

含義一:與普通INSERT一樣功能

REPLACE INTO score (change_type,score,user_id) VALUES ('吃飯',10,1),('喝茶',10,1),('喝茶',10,1);

含義二:找到第一條記錄,用后面的值進行替換

REPLACE INTO score (id,change_type,score,user_id) VALUES (1,'吃飯',10,1)

此語句的作用是向表table中插入3條記錄。如果主鍵id為1或2不存在就相當于插入語句:

INSERT INTO score (change_type,score,user_id) VALUES (‘吃飯’,10,1),(‘喝茶’,10,1),(‘喝茶’,10,1);

如果存在相同的值則不會插入數(shù)據(jù)。

(2)replace(object, search, replace),把object中出現(xiàn)search的全部替換為replace。

用法一:并不是修改數(shù)據(jù),而只是單純做局部替換數(shù)據(jù)返還而已。

SELECT REPLACE('喝茶','茶','喝')//結果: 喝喝123

用法二:修改表數(shù)據(jù)啦,對應下面就是,根據(jù)change_type字段找到做任務的數(shù)據(jù),用bb來替換

UPDATE score SET change_type=REPLACE(change_type,'做任務','bb')1

在此,做下對比:UPDATE和REPLACE的區(qū)別:

1)UPDATE在沒有匹配記錄時什么都不做,而REPLACE在有重復記錄時更新,在沒有重復記錄時插入。

2)UPDATE可以選擇性地更新記錄的一部分字段。而REPLACE在發(fā)現(xiàn)有重復記錄時就將這條記錄徹底刪除,再插入新的記錄。也就是說,將所有的字段都更新了。

其實REPLACE更像INSERT與DELETE的結合。


單表查詢優(yōu)化

(0)可以先使用EXPLAIN關鍵字可以讓你知道MySQL是如何處理你的SQL語句的。這可以幫我們分析是查詢語句或是表結構的性能瓶頸。

(1)寫sql要明確需要的字段,要多少就寫多少字段,而不是濫用 select *

(2)可以用使用連接(JOIN)來代替子查詢

(3)使用分頁語句:limit start , count 或者條件 where子句時,有什么可限制的條件盡量加上,查一條就limit一條。做到不濫用。比如說我之前做過的的p2p項目,只是需要知道有沒有一個滿標的借款,這樣的話就可以用上 limit 1,這樣mysql在找到一條數(shù)據(jù)后就停止搜索,而不是全文搜索完再停止。

(4)開啟查詢緩存:

大多數(shù)的MySQL服務器都開啟了查詢緩存。這是提高查詢有效的方法之一。當有很多相同的查詢被執(zhí)行了多次的時候,這些查詢結果會被放到一個緩存中,這樣,后續(xù)的相同的查詢就不用操作表而直接訪問緩存結果了。

查詢緩存工作流程:

A):服務器接收SQL,以SQL+DB+Query_cache_query_flags作為hash查找鍵;

B):找到了相關的結果集就將其返回給客戶端;

C):如果沒有找到緩存則執(zhí)行權限驗證、SQL解析、SQL優(yōu)化等一些列的操作;

D):執(zhí)行完SQL之后,將結果集保存到緩存

當然,并不是每種情況都適合使用緩存,衡量打開緩存是否對系統(tǒng)有性能提升是一個整體的概念。那怎么判斷要不要開啟緩存呢,如下:

1)通過緩存命中率判斷, 緩存命中率 = 緩存命中次數(shù) (Qcache_hits) / 查詢次數(shù) (Com_select)、

2)通過緩存寫入率, 寫入率 = 緩存寫入次數(shù) (Qcache_inserts) / 查詢次數(shù) (Qcache_inserts)

3)通過 命中-寫入率 判斷, 比率 = 命中次數(shù) (Qcache_hits) / 寫入次數(shù) (Qcache_inserts), 高性能MySQL中稱之為比較能反映性能提升的指數(shù),一般來說達到3:1則算是查詢緩存有效,而最好能夠達到10:1

相關參數(shù)及命令:

與緩存相關的主要參數(shù)如下表所示??梢允褂妹?b>SHOW VARIABLES LIKE '%query_cache%'查看

緩存數(shù)據(jù)失效時機

在表的結構或數(shù)據(jù)發(fā)生改變時,查詢緩存中的數(shù)據(jù)不再有效。有這些INSERT、UPDATE、 DELETE、TRUNCATE、ALTER TABLE、DROP TABLE或DROP DATABASE會導致緩存數(shù)據(jù)失效。所以查詢緩存適合有大量相同查詢的應用,不適合有大量數(shù)據(jù)更新的應用。

可以使用下面三個SQL來清理查詢緩存:

1、FLUSH QUERY CACHE; // 清理查詢緩存內(nèi)存碎片。

2、RESET QUERY CACHE; // 從查詢緩存中移出所有查詢。

3、FLUSH TABLES; //關閉所有打開的表,同時該操作將會清空查詢緩存中的內(nèi)容。

InnoDB與查詢緩存:

Innodb會對每個表設置一個事務計數(shù)器,里面存儲當前最大的事務ID.當一個事務提交時,InnoDB會使用MVCC中系統(tǒng)事務ID最大的事務ID跟新當前表的計數(shù)器.

只有比這個最大ID大的事務能使用查詢緩存,其他比這個ID小的事務則不能使用查詢緩存.

另外,在InnoDB中,所有有加鎖操作的事務都不使用任何查詢緩存

(MVCC (Multiversion Concurrency Control),即多版本并發(fā)控制技術,它使得大部分支持行鎖的事務引擎,不再單純的使用行鎖來進行數(shù)據(jù)庫的并發(fā)控制,取而代之的是把數(shù)據(jù)庫的行鎖與行的多個版本結合起來,只需要很小的開銷,就可以實現(xiàn)非鎖定讀,從而大大提高數(shù)據(jù)庫系統(tǒng)的并發(fā)性能)

多表查詢連接的選擇:

相信這內(nèi)連接,左連接什么的大家都比較熟悉了,當然還有左外連接什么的,基本用不上我就不貼出來了。這圖只是讓大家回憶一下,各種連接查詢。 然后要告訴大家的是,需要根據(jù)查詢的情況,想好使用哪種連接方式效率更高。

二、MySQL的JOIN實現(xiàn)原理

在MySQL 中,只有一種Join 算法,就是大名鼎鼎的Nested Loop Join,他沒有其他很多數(shù)據(jù)庫所提供的Hash Join,也沒有Sort Merge Join。顧名思義,Nested Loop Join 實際上就是通過驅動表的結果集作為循環(huán)基礎數(shù)據(jù),然后一條一條的通過該結果集中的數(shù)據(jù)作為過濾條件到下一個表中查詢數(shù)據(jù),然后合并結果。如果還有第三個參與Join,則再通過前兩個表的Join 結果集作為循環(huán)基礎數(shù)據(jù),再一次通過循環(huán)查詢條件到第三個表中查詢數(shù)據(jù),如此往復。 ——摘自《MySQL 性能調(diào)優(yōu)與架構設計》

三、補充:mysql對sql語句的容錯問題

即在sql語句不完全符合書寫建議的情況,mysql會允許這種情況,盡可能解釋它:

1)一般cross join后面加上where條件,但是用cross join+on也是被解釋為cross join+where

2)一般內(nèi)連接都需要加上on限定條件,如上面場景一;如果不加會被解釋為交叉連接;

3)如果連接表格使用的是逗號,會被解釋為交叉連接;

超大型數(shù)據(jù)盡可能盡力不要寫子查詢,使用連接(JOIN)去替換它:

當然,關于這句話,也不一定就全是這樣。

1)因為在大型的數(shù)據(jù)處理中,子查詢是非常常見的,特別是在查詢出來的數(shù)據(jù)需要進一步處理的情況,無論是可讀性還是效率上,這時候的子查都是更優(yōu)。

2)然而在一些特定的場景,可以直接從數(shù)據(jù)庫讀取就可以的,比如一個表(A表 a,b,c字段,需要內(nèi)部數(shù)據(jù)交集)join自己的效率必然比放一個子查在where中快得多。

使用聯(lián)合(UNION)來代替手動創(chuàng)建的臨時表

UNION是會把結果排序的?。?!

union查詢:它可以把需要使用臨時表的兩條或更多的select查詢合并的一個查詢中(即把兩次或多次查詢結果合并起來。)。在客戶端的查詢會話結束的時候,臨時表會被自動刪除,從而保證數(shù)據(jù)庫整齊、高效。使用union來創(chuàng)建查詢的時候,我們只需要用UNION作為關鍵字把多個select語句連接起來就可以了,要注意的是所有select語句中的字段數(shù)目要想同。

要求:兩次查詢的列數(shù)必須一致(列的類型可以不一樣,但推薦查詢的每一列,相對應的類型要一樣)

可以來自多張表的數(shù)據(jù):多次sql語句取出的列名可以不一致,此時以第一個sql語句的列名為準。

如果不同的語句中取出的行,有完全相同(這里表示的是每個列的值都相同),那么union會將相同的行合并,最終只保留一行。也可以這樣理解,union會去掉重復的行。

如果不想去掉重復的行,可以使用union all。

如果子句中有order by,limit,需用括號()包起來。推薦放到所有子句之后,即對最終合并的結果來排序或篩選。

注意:

1、UNION 結果集中的列名總是等于第一個 SELECT 語句中的列名

2、UNION 內(nèi)部的 SELECT 語句必須擁有相同數(shù)量的列。列也必須擁有相似的數(shù)據(jù)類型。同時,每條 SELECT 語句中的列的順序必須相同

UNION ALL的作用和語法:

默認地,UNION 操作符選取不同的值。如果允許重復的值,請使用 UNION ALL。當 ALL 隨 UNION 一起使用時(即 UNION ALL),不消除重復行。

總結

(1)對于要求全面的結果時,我們需要使用連接操作(LEFT JOIN / RIGHT JOIN / FULL JOIN);

(2)應盡量避免在 where 子句中對字段進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描,如:

備注、描述、評論之類的可以設置為 NULL,其他最好不要使用NULL。

不要以為 NULL 不需要空間,比如:char(100) 型,在字段建立時,空間就固定了, 不管是否插入值(NULL也包含在內(nèi)),都是占用 100個字符的空間的,如果是varchar這樣的變長字段, null 不占用空間。

可以在num上設置默認值0,確保表中num列沒有null值,然后這樣查詢:

select id from t where num = 0

(3)in 和 not in 也要慎用,否則會導致全表掃描,如:

對于連續(xù)的數(shù)值,能用 between 就不要用 in 了:

很多時候用 exists 代替 in 是一個好的選擇:

(4)盡量使用數(shù)字型字段,若只含數(shù)值信息的字段盡量不要設計為字符型,這會降低查詢和連接的性能,并會增加存儲開銷。這是因為引擎在處理查詢和連 接時會逐個比較字符串中每一個字符,而對于數(shù)字型而言只需要比較一次就夠了。

(5)盡量使用表變量來代替臨時表。如果表變量包含大量數(shù)據(jù),請注意索引非常有限(只有主鍵索引)。

(6)不要以為使用MySQL的一些連接操作對查詢有多么大的改善,其實核心是索引


?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,533評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,055評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,365評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,561評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,346評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,889評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,978評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,118評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,637評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,558評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,739評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,246評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 43,980評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,619評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,347評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,702評論 2 370

推薦閱讀更多精彩內(nèi)容