日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > 数据库 >内容正文

数据库

mysql 优化表的作用_mysql实战优化之三:表优化

發(fā)布時(shí)間:2023/12/18 数据库 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql 优化表的作用_mysql实战优化之三:表优化 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

對(duì)于大多數(shù)的數(shù)據(jù)庫(kù)引擎來(lái)說(shuō),硬盤操作可能是最重大的瓶頸。所以,把你的數(shù)據(jù)變得緊湊會(huì)對(duì)這種情況非常有幫助,因?yàn)檫@減少了對(duì)硬盤的訪問(wèn)。

如果一個(gè)表只會(huì)有幾列罷了(比如說(shuō)字典表,配置表),那么,我們就沒(méi)有理由使用 INT 來(lái)做主鍵,使用 MEDIUMINT, SMALLINT 或是更小的 TINYINT 會(huì)更經(jīng)濟(jì)一些。如果你不需要記錄時(shí)間,使用 DATE 要比 DATETIME 好得多。

當(dāng)然,你也需要留夠足夠的擴(kuò)展空間,不然,你日后來(lái)干這個(gè)事,你會(huì)死的很難看,參看Slashdot的例子(2009年11月06 日),一個(gè)簡(jiǎn)單的ALTER TABLE語(yǔ)句花了3個(gè)多小時(shí),因?yàn)槔锩嬗幸磺Я偃f(wàn)條數(shù)據(jù)。

表結(jié)構(gòu)優(yōu)化

一、數(shù)據(jù)類型選擇

數(shù)據(jù)庫(kù)操作中最為耗時(shí)的操作就是 IO 處理,大部分?jǐn)?shù)據(jù)庫(kù)操作 90% 以上的時(shí)間都花在了 IO 讀寫上面。所以盡可能減少 IO 讀寫量,可以在很大程度上提高數(shù)據(jù)庫(kù)操作的性能。

我們無(wú)法改變數(shù)據(jù)庫(kù)中需要存儲(chǔ)的數(shù)據(jù),但是我們可以在這些數(shù)據(jù)的存儲(chǔ)方式方面花一些心思。下面的這些關(guān)于字段類型的優(yōu)化建議主要適用于記錄條數(shù)較多,數(shù)據(jù)量較大的場(chǎng)景,因?yàn)榫?xì)化的數(shù)據(jù)類型設(shè)置可能帶來(lái)維護(hù)成本的提高,過(guò)度優(yōu)化也可能會(huì)帶來(lái)其他的問(wèn)題:

1.數(shù)字類型:非萬(wàn)不得已不要使用DOUBLE,不僅僅只是存儲(chǔ)長(zhǎng)度的問(wèn)題,同時(shí)還會(huì)存在精確性的問(wèn)題。同樣,固定精度的小數(shù),也不建議使用DECIMAL,建議乘以固定倍數(shù)轉(zhuǎn)換成整數(shù)存儲(chǔ),可以大大節(jié)省存儲(chǔ)空間,且不會(huì)帶來(lái)任何附加維護(hù)成本。對(duì)于整數(shù)的存儲(chǔ),在數(shù)據(jù)量較大的情況下,建議區(qū)分開(kāi) TINYINT / INT / BIGINT 的選擇,因?yàn)槿咚加玫拇鎯?chǔ)空間也有很大的差別,能確定不會(huì)使用負(fù)數(shù)的字段,建議添加unsigned定義。當(dāng)然,如果數(shù)據(jù)量較小的數(shù)據(jù)庫(kù),也可以不用嚴(yán)格區(qū)分三個(gè)整數(shù)類型。

2.字符類型:非萬(wàn)不得已不要使用 TEXT 數(shù)據(jù)類型,其處理方式?jīng)Q定了他的性能要低于char或者是varchar類型的處理。定長(zhǎng)字段,建議使用 CHAR 類型,不定長(zhǎng)字段盡量使用 VARCHAR,且僅僅設(shè)定適當(dāng)?shù)淖畲箝L(zhǎng)度,而不是非常隨意的給一個(gè)很大的最大長(zhǎng)度限定,因?yàn)椴煌拈L(zhǎng)度范圍,MySQL也會(huì)有不一樣的存儲(chǔ)處理。

3.時(shí)間類型:盡量使用TIMESTAMP類型,因?yàn)槠浯鎯?chǔ)空間只需要 DATETIME 類型的一半。對(duì)于只需要精確到某一天的數(shù)據(jù)類型,建議使用DATE類型,因?yàn)樗拇鎯?chǔ)空間只需要3個(gè)字節(jié),比TIMESTAMP還少。不建議通過(guò)INT類型類存儲(chǔ)一個(gè)unix timestamp 的值,因?yàn)檫@太不直觀,會(huì)給維護(hù)帶來(lái)不必要的麻煩,同時(shí)還不會(huì)帶來(lái)任何好處。

4.ENUM & SET:對(duì)于狀態(tài)字段,可以嘗試使用 ENUM 來(lái)存放,因?yàn)榭梢詷O大的降低存儲(chǔ)空間,而且即使需要增加新的類型,只要增加于末尾,修改結(jié)構(gòu)也不需要重建表數(shù)據(jù)。如果是存放可預(yù)先定義的屬性數(shù)據(jù)呢?可以嘗試使用SET類型,即使存在多種屬性,同樣可以游刃有余,同時(shí)還可以節(jié)省不小的存儲(chǔ)空間。

5.LOB類型:強(qiáng)烈反對(duì)在數(shù)據(jù)庫(kù)中存放 LOB 類型數(shù)據(jù),雖然數(shù)據(jù)庫(kù)提供了這樣的功能,但這不是他所擅長(zhǎng)的,我們更應(yīng)該讓合適的工具做他擅長(zhǎng)的事情,才能將其發(fā)揮到極致。在數(shù)據(jù)庫(kù)中存儲(chǔ) LOB 數(shù)據(jù)就像讓一個(gè)多年前在學(xué)校學(xué)過(guò)一點(diǎn)Java的營(yíng)銷專業(yè)人員來(lái)寫 Java 代碼一樣。

二、字符編碼

字符集直接決定了數(shù)據(jù)在MySQL中的存儲(chǔ)編碼方式,由于同樣的內(nèi)容使用不同字符集表示所占用的空間大小會(huì)有較大的差異,所以通過(guò)使用合適的字符集,可以幫助我們盡可能減少數(shù)據(jù)量,進(jìn)而減少IO操作次數(shù)。

1.純拉丁字符能表示的內(nèi)容,沒(méi)必要選擇 latin1 之外的其他字符編碼,因?yàn)檫@會(huì)節(jié)省大量的存儲(chǔ)空間

2.如果我們可以確定不需要存放多種語(yǔ)言,就沒(méi)必要非得使用UTF8或者其他UNICODE字符類型,這回造成大量的存儲(chǔ)空間浪費(fèi)

3.MySQL的數(shù)據(jù)類型可以精確到字段,所以當(dāng)我們需要大型數(shù)據(jù)庫(kù)中存放多字節(jié)數(shù)據(jù)的時(shí)候,可以通過(guò)對(duì)不同表不同字段使用不同的數(shù)據(jù)類型來(lái)較大程度減小數(shù)據(jù)存儲(chǔ)量,進(jìn)而降低 IO 操作次數(shù)并提高緩存命中率

三、適當(dāng)拆分

有些時(shí)候,我們可能會(huì)希望將一個(gè)完整的對(duì)象對(duì)應(yīng)于一張數(shù)據(jù)庫(kù)表,這對(duì)于應(yīng)用程序開(kāi)發(fā)來(lái)說(shuō)是很有好的,但是有些時(shí)候可能會(huì)在性能上帶來(lái)較大的問(wèn)題。

當(dāng)我們的表中存在類似于 TEXT 或者是很大的 VARCHAR類型的大字段的時(shí)候,如果我們大部分訪問(wèn)這張表的時(shí)候都不需要這個(gè)字段,我們就該義無(wú)反顧的將其拆分到另外的獨(dú)立表中,以減少常用數(shù)據(jù)所占用的存儲(chǔ)空間。這樣做的一個(gè)明顯好處就是每個(gè)數(shù)據(jù)塊中可以存儲(chǔ)的數(shù)據(jù)條數(shù)可以大大增加,既減少物理 IO 次數(shù),也能大大提高內(nèi)存中的緩存命中率。

上面幾點(diǎn)的優(yōu)化都是為了減少每條記錄的存儲(chǔ)空間大小,讓每個(gè)數(shù)據(jù)庫(kù)中能夠存儲(chǔ)更多的記錄條數(shù),以達(dá)到減少 IO 操作次數(shù),提高緩存命中率。下面這個(gè)優(yōu)化建議可能很多開(kāi)發(fā)人員都會(huì)覺(jué)得不太理解,因?yàn)檫@是典型的反范式設(shè)計(jì),而且也和上面的幾點(diǎn)優(yōu)化建議的目標(biāo)相違背。

四、適度冗余

為什么我們要冗余?這不是增加了每條數(shù)據(jù)的大小,減少了每個(gè)數(shù)據(jù)塊可存放記錄條數(shù)嗎?

確實(shí),這樣做是會(huì)增大每條記錄的大小,降低每條記錄中可存放數(shù)據(jù)的條數(shù),但是在有些場(chǎng)景下我們?nèi)匀贿€是不得不這樣做:

被頻繁引用且只能通過(guò) Join 2張(或者更多)大表的方式才能得到的獨(dú)立小字段

這樣的場(chǎng)景由于每次Join僅僅只是為了取得某個(gè)小字段的值,Join到的記錄又大,會(huì)造成大量不必要的 IO,完全可以通過(guò)空間換取時(shí)間的方式來(lái)優(yōu)化。不過(guò),冗余的同時(shí)需要確保數(shù)據(jù)的一致性不會(huì)遭到破壞,確保更新的同時(shí)冗余字段也被更新

五、盡量使用 NOT NULLNULL 類型比較特殊,SQL 難優(yōu)化。雖然 MySQL NULL類型和 Oracle 的NULL 有差異,會(huì)進(jìn)入索引中,但如果是一個(gè)組合索引,那么這個(gè)NULL 類型的字段會(huì)極大影響整個(gè)索引的效率。此外,NULL 在索引中的處理也是特殊的,也會(huì)占用額外的存放空間。

很多人覺(jué)得 NULL 會(huì)節(jié)省一些空間,所以盡量讓NULL來(lái)達(dá)到節(jié)省IO的目的,但是大部分時(shí)候這會(huì)適得其反,雖然空間上可能確實(shí)有一定節(jié)省,倒是帶來(lái)了很多其他的優(yōu)化問(wèn)題,不但沒(méi)有將IO量省下來(lái),反而加大了SQL的IO量。所以盡量確保 DEFAULT 值不是 NULL,也是一個(gè)很好的表結(jié)構(gòu)設(shè)計(jì)優(yōu)化習(xí)慣。

六、分離冷熱數(shù)據(jù)

將大字段、訪問(wèn)頻率低的字段拆分到單獨(dú)的表中存儲(chǔ),分離冷熱數(shù)據(jù),有利于有效利用緩存,防止讀入無(wú)用的冷數(shù)據(jù),較少磁盤IO,同時(shí)保證熱數(shù)據(jù)常駐內(nèi)存提高緩存命中率。

六、避免大表的DDL操作

MYSQL的新增和修改列的操作相當(dāng)于重建表,表設(shè)計(jì)要一步到位,盡量避免大表的DDL操作。 (TIPS:可以預(yù)定義一些列留作將來(lái)業(yè)務(wù)擴(kuò)展,如:當(dāng)前只需要10個(gè)字段,考慮到未來(lái)發(fā)展,可以預(yù)留10個(gè)字段,表上總共創(chuàng)建20個(gè)字段)

七、定期分析表和檢查表

分析表的語(yǔ)法:ANALYZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tb1_name[, tbl_name]...

以上語(yǔ)句用于分析和存儲(chǔ)表的關(guān)鍵字分布,分析的結(jié)果將可以使得系統(tǒng)得到準(zhǔn)確的統(tǒng)計(jì)信息,使得SQL能夠生成正確的執(zhí)行計(jì)劃。如果用戶感覺(jué)實(shí)際執(zhí)行計(jì) 劃并不是預(yù)期的執(zhí)行計(jì)劃,執(zhí)行一次分析表可能會(huì)解決問(wèn)題。在分析期間,使用一個(gè)讀取鎖定對(duì)表進(jìn)行鎖定。這對(duì)于MyISAM,DBD和InnoDB表有作 用。

例如分析一個(gè)數(shù)據(jù)表:analyze table table_name

檢查表的語(yǔ)法:CHECK TABLE tb1_name[,tbl_name]...[option]...option = {QUICK | FAST | MEDIUM | EXTENDED | CHANGED}

檢查表的作用是檢查一個(gè)或多個(gè)表是否有錯(cuò)誤,CHECK TABLE 對(duì)MyISAM 和 InnoDB表有作用,對(duì)于MyISAM表,關(guān)鍵字統(tǒng)計(jì)數(shù)據(jù)被更新

CHECK TABLE 也可以檢查視圖是否有錯(cuò)誤,比如在視圖定義中被引用的表不存在。

八、定期優(yōu)化表

定期分析表

ANALYZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_name [, tbl_name]

本語(yǔ)句用于分析和存儲(chǔ)表的關(guān)鍵字分布。在分析期間,使用一個(gè)讀取鎖定對(duì)表進(jìn)行鎖定。這對(duì)于MyISAM, BDB和InnoDB表有作用。對(duì)于MyISAM表,本語(yǔ)句與使用myisamchk -a相當(dāng)。

MySQL使用已存儲(chǔ)的關(guān)鍵字分布來(lái)決定,當(dāng)您對(duì)除常數(shù)以外的對(duì)象執(zhí)行聯(lián)合時(shí),表按什么順序進(jìn)行聯(lián)合。

mysql> analyze table a;

+--------+---------+----------+-----------------------------+

| Table ?| Op ? ? ?| Msg_type | Msg_text ? ? ? ? ? ? ? ? ? ?|

+--------+---------+----------+-----------------------------+

| test.a | analyze | status ? | Table is already up to date |

+--------+---------+----------+-----------------------------+

1 row in set (0.00 sec)

定期檢查表

CHECK TABLE tbl_name [, tbl_name] ?[option]

option = {QUICK | FAST | MEDIUM | EXTENDED | CHANGED}

檢查一個(gè)或多個(gè)表是否有錯(cuò)誤。CHECK TABLE對(duì)MyISAM和InnoDB表有作用。對(duì)于MyISAM表,關(guān)鍵字統(tǒng)計(jì)數(shù)據(jù)被更新。

mysql> check table a;

+--------+-------+----------+----------+

| Table ?| Op ? ?| Msg_type | Msg_text |

+--------+-------+----------+----------+

| test.a | check | status ? | OK ? ? ? |

+--------+-------+----------+----------+

1 row in set (0.00 sec)

CHECK TABLE也可以檢查視圖是否有錯(cuò)誤,比如在視圖定義中被引用的表已不存在。

我們?yōu)樯厦娴谋韆創(chuàng)建一個(gè)視圖

mysql> create view a_view as select * from a;

Query OK, 0 rows affected (0.02 sec)

然后CHECK一下該視圖,發(fā)現(xiàn)沒(méi)有問(wèn)題

mysql> check table a_view;

+-------------+-------+----------+----------+

| Table ? ? ? | Op ? ?| Msg_type | Msg_text |

+-------------+-------+----------+----------+

| test.a_view | check | status ? | OK ? ? ? |

+-------------+-------+----------+----------+

1 row in set (0.00 sec)

現(xiàn)在刪掉視圖依賴的表

mysql> drop table a;

Query OK, 0 rows affected (0.01 sec)

再CHECK一下剛才的視圖,發(fā)現(xiàn)報(bào)錯(cuò)了

mysql> check table a_view\G;

*************************** 1. row ***************************

Table: test.a_view

Op: check

Msg_type: Error

Msg_text: Table 'test.a' doesn't exist

*************************** 2. row ***************************

Table: test.a_view

Op: check

Msg_type: Error

Msg_text: View 'test.a_view' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them

*************************** 3. row ***************************

Table: test.a_view

Op: check

Msg_type: error

Msg_text: Corrupt

3 rows in set (0.00 sec)

ERROR:

No query specified

定期優(yōu)化表

OPTIMIZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_name [, tbl_name]

如果您已經(jīng)刪除了表的一大部分,或者如果您已經(jīng)對(duì)含有可變長(zhǎng)度行的表(含有VARCHAR, BLOB或TEXT列的表)進(jìn)行了很多更改,則應(yīng)使用OPTIMIZE TABLE。被刪除的記錄被保持在鏈接清單中,后續(xù)的INSERT操作會(huì)重新使用舊的記錄位置。您可以使用OPTIMIZE TABLE來(lái)重新利用未使用的空間,并整理數(shù)據(jù)文件的碎片。

在多數(shù)的設(shè)置中,您根本不需要運(yùn)行OPTIMIZE TABLE。即使您對(duì)可變長(zhǎng)度的行進(jìn)行了大量的更新,您也不需要經(jīng)常運(yùn)行,每周一次或每月一次即可,只對(duì)特定的表運(yùn)行。

OPTIMIZE TABLE只對(duì)MyISAM, BDB和InnoDB表起作用。

對(duì)于MyISAM表,OPTIMIZE TABLE按如下方式操作:

如果表已經(jīng)刪除或分解了行,則修復(fù)表。

如果未對(duì)索引頁(yè)進(jìn)行分類,則進(jìn)行分類。

如果表的統(tǒng)計(jì)數(shù)據(jù)沒(méi)有更新(并且通過(guò)對(duì)索引進(jìn)行分類不能實(shí)現(xiàn)修復(fù)),則進(jìn)行更新。

mysql> OPTIMIZE table a;

+--------+----------+----------+-----------------------------+

| Table ?| Op ? ? ? | Msg_type | Msg_text ? ? ? ? ? ? ? ? ? ?|

+--------+----------+----------+-----------------------------+

| test.a | optimize | status ? | Table is already up to date |

+--------+----------+----------+-----------------------------+

1 row in set (0.00 sec)

****

需要注意的是無(wú)論是ANALYZE,CHECK還是OPTIMIZE在執(zhí)行期間將對(duì)表進(jìn)行鎖定,因此請(qǐng)注意這些操作要在數(shù)據(jù)庫(kù)不繁忙的時(shí)候執(zhí)行

****

表結(jié)構(gòu)優(yōu)化可以使用Procedure Analyse()幫助分析。詳細(xì)見(jiàn)《

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的mysql 优化表的作用_mysql实战优化之三:表优化的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。