MySQL表的定期分析檢查優化


Analyze Table 分析表
 

MySQL 的Optimizer(優化元件)在優化SQL語句時,首先需要收集一些相關信息,其中就包括表的cardinality(可以翻譯為“散列程度”),它表示某個索引對應的列包含多少個不同的值——如果cardinality大大少於數據的實際散列程度,那么索引就基本失效了。
我們可以使用SHOW INDEX語句來查看索引的散列程度:

SHOW INDEX FROM PLAYERS;

TABLE   KEY_NAME COLUMN_NAME CARDINALITY
------- -------- ----------- -----------
PLAYERS PRIMARY PLAYERNO             14

因為此時PLAYER表中不同的PLAYERNO數量遠遠多於14,索引基本失效。
下面我們通過Analyze Table語句來修復索引:

ANALYZE TABLE PLAYERS;
SHOW INDEX FROM PLAYERS;
結果是:
TABLE   KEY_NAME COLUMN_NAME CARDINALITY
------- -------- ----------- -----------
PLAYERS PRIMARY PLAYERNO           1000

此時索引已經修復,查詢效率大大提高。

需要注意的是,如果開啟了binlog,那么Analyze Table的結果也會寫入binlog,我們可以在analyze和table之間添加關鍵字local取消寫入。

 

 
Check Table 檢查表
 

數據庫經常可能遇到錯誤,譬如數據寫入磁盤時發生錯誤,或是索引沒有同步更新,或是數據庫未關閉MySQL就停止了。
遇到這些情況,數據就可能發生錯誤:
Incorrect key file for table: ' '. Try to repair it.
此時,我們可以使用Check Table語句來檢查表及其對應的索引。


檢查一個或多個表是否有錯誤。CHECK TABLE對MyISAM和InnoDB表有作用。對於MyISAM表,關鍵字統計數據被更新。

mysql> check table a;
+--------+-------+----------+----------+
| Table  | Op    | Msg_type | Msg_text |
+--------+-------+----------+----------+
| test.a | check | status   | OK       | 
+--------+-------+----------+----------+
1 row in set (0.00 sec)
 
CHECK TABLE也可以檢查視圖是否有錯誤,比如在視圖定義中被引用的表已不存在。
我們為上面的表a創建一個視圖 
mysql> create view a_view as select * from a;
Query OK, 0 rows affected (0.02 sec)
 
然后CHECK一下該視圖,發現沒有問題
mysql> check table a_view;
+-------------+-------+----------+----------+
| Table       | Op    | Msg_type | Msg_text |
+-------------+-------+----------+----------+
| test.a_view | check | status   | OK       | 
+-------------+-------+----------+----------+
1 row in set (0.00 sec)
 
現在刪掉視圖依賴的表
mysql> drop table a;
Query OK, 0 rows affected (0.01 sec)
 
再CHECK一下剛才的視圖,發現報錯了
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
 
  Check Table還可以指定其它選項:
UPGRADE:用來測試在更早版本的MySQL中建立的表是否與當前版本兼容。
QUICK:速度最快的選項,在檢查各列的數據時,不會檢查鏈接(link)的正確與否,如果沒有遇到什么問題,可以使用這個選項。
FAST:只檢查表是否正常關閉,如果在系統掉電之后沒有遇到嚴重問題,可以使用這個選項。
CHANGED:只檢查上次檢查時間之后更新的數據。
MEDIUM:默認的選項,會檢查索引文件和數據文件之間的鏈接正確性。
EXTENDED:最慢的選項,會進行全面的檢查。
 
Checksum Table

數據在傳輸時,可能會發生變化,也有可能因為其它原因損壞,為了保證數據的一致,我們可以計算checksum(校驗值)。
使用MyISAM引擎的表會把checksum存儲起來,稱為live checksum,當數據發生變化時,checksum會相應變化。
在執行Checksum Table時,可以在最后指定選項qiuck或是extended;quick表示返回存儲的checksum值,而extended會重新計算checksum,如果沒有指定選項,則默認使用extended。
 
 
Optimize Table 優化表
 
OPTIMIZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_name [, tbl_name] 
 
如果您已經刪除了表的一大部分,或者如果您已經對含有可變長度行的表(含有VARCHAR, BLOB或TEXT列的表)進行了很多更改,則應使用OPTIMIZE TABLE。被刪除的記錄被保持在鏈接清單中,后續的INSERT操作會重新使用舊的記錄位置。您可以使用OPTIMIZE TABLE來重新利用未使用的空間,並整理數據文件的碎片。
在多數的設置中,您根本不需要運行OPTIMIZE TABLE。即使您對可變長度的行進行了大量的更新,您也不需要經常運行,每周一次或每月一次即可,只對特定的表運行。
OPTIMIZE TABLE只對MyISAM, BDB和InnoDB表起作用。
對於MyISAM表,OPTIMIZE TABLE按如下方式操作:
如果表已經刪除或分解了行,則修復表。
如果未對索引頁進行分類,則進行分類。
如果表的統計數據沒有更新(並且通過對索引進行分類不能實現修復),則進行更新。 
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)
 
Repair Table 修復表

用於修復表,只對MyISAM和ARCHIVE類型的表有效。
這條語句同樣可以指定選項:
QUICK:最快的選項,只修復索引樹。
EXTENDED:最慢的選項,需要逐行重建索引。
USE_FRM:只有當MYI文件丟失時才使用這個選項,全面重建整個索引。

與Analyze Table一樣,Repair Table也可以使用local來取消寫入binlog。
 
****
需要注意的是無論是ANALYZE,CHECK還是OPTIMIZE在執行期間將對表進行鎖定,因此請注意這些操作要在 數據庫不繁忙的時候執行
****
 
 

2012-11-22 13:04 by 軒脈刃, 1318 閱讀, 5 評論, 收藏編輯

show table status

mysql官方文檔在

http://dev.mysql.com/doc/refman/5.1/en/show-table-status.html

這里的rows行是表的行數,但是實際上是不准的。myisam是准的,其他的存儲引擎是不准的。要准確的行數就需要使用count(*) 來獲取了。

mysql執行大批量刪除

執行大批量刪除的時候注意要使用上limit

因為如果不用limit,刪除大量數據很有可能造成死鎖

如果delete的where語句不在索引上,可以先找主鍵,然后根據主鍵刪除數據庫

ps: 平時update和delete的時候最好也加上limit 1 來防止誤操作

optimize、Analyze、check、repair維護操作

l optimize 數據在插入,更新,刪除的時候難免一些數據遷移,分頁,之后就出現一些碎片,久而久之碎片積累起來影響性能,這就需要DBA定期的優化數據庫減少碎片,這就通過optimize命令。

如對MyisAM表操作:optimize table 表名

對於InnoDB表是不支持optimize操作,否則提示“Table does not support optimize, doing recreate + analyze instead”,當然也可以通過命令:alter table one type=innodb; 來替代。

l Analyze 用來分析和存儲表的關鍵字的分布,使得系統獲得准確的統計信息,影響 SQL 的執行計划的生成。對於數據基本沒有發生變化的表,是不需要經常進行表分析的。但是如果表的數據量變化很明顯,用戶感覺實際的執行計划和預期的執行計划不 同的時候,執行一次表分析可能有助於產生預期的執行計划。

Analyze table 表名

l Check檢查表或者視圖是否存在錯誤,對 MyISAM 和 InnoDB 存儲引擎的表有作用。對於 MyISAM 存儲引擎的表進行表檢查,也會同時更新關鍵字統計數據

l Repair optimize需要有足夠的硬盤空間,否則可能會破壞表,導致不能操作,那就要用上repair,注意INNODB不支持repair操作

生成亂序的id

方法:

使用預設表

比如id和toid的映射

其中id是固定的,toid是隨機的。

然后在redis或memcache中記錄一個指針值,指向id

當要獲取一個新toid的時候,取出指針值,加1,然后去預設表中獲取toid

查詢和索引

查詢的時候必須要考慮到如何命中索引

比如有幾個小招:

1 不要在索引列中使用表達式

where mycol *2 < 4

2 不要在like模式的開始位置使用通配符%

where col_name like ‘%string%’

不如

where col_name like ‘string%’

3 避免過多使用mysql自動轉換類型,有可能無法用到index

比如

select * from mytbl where str_col=4

但是str_col為字符串,這里其實就隱含了字符串變化

應該使用

select * from mytbl where str_col=’4’

索引比表還大就不需要建立索引了嗎

索引是按照順序排列的。所以即使索引比表大,也是可以加快查詢速度的。

當然如果索引比表還大首要的任務必須是檢查下索引建立地是否有問題

Char和varchar如何選擇

char是定長,varchar變長 
varchar除了設置了數據之外,還多使用1兩個字節定義了數據實際長度。

char會在后面空余的行填充上空字符串

myisam建議使用char。myisam中有個靜態表的概念。使用char比使用varchar的查詢效率高很多。

innodb建議使用varchar。主要是從節省空間的方面考慮

多個TimeStamp設置默認值

一個表中至多只能有一個字段設置CURRENT_TIMESTAMP

對於下面的需求:

一個表中,有兩個字段,createtime和updatetime。

1 當insert的時候,sql兩個字段都不設置,會設置為當前的時間

2 當update的時候,sql中兩個字段都不設置,updatetime會變更為當前的時間

這樣的需求是做不到的。因為你無法避免在兩個字段上設置CURRENT_TIMESTAMP

 

解決辦法有幾個:

1 使用觸發器。

2 將第一個timestamp的default設置為0

3 老老實實在sql語句中使用時間戳。

http://www.cnblogs.com/yjf512/archive/2012/11/02/2751058.html

查詢數據表有多少行,多少容量

不要使用select count(*)

使用show table status like ‘table_name’  但是innodb的話會有50%左右的浮動,是個預估值

AUTO_INCREMENT的設置

1 不要設置為int,請設置為unsinged int,auto_increment的范圍是根據類型來判定的

2 auto_increment數據列必須要有索引,並且保證唯一性。

3 auto_increment必須有NOT NULL屬性

4 auto_increment可以使用

UPDATE table SET seq = LAST_INSERT_ID(seq -1)

mysql的表示時間的字段用什么類型

表示時間可以使用timestamp和datetime來使用

datetime表示的時間可以從0000-00-00:00:00 到9999-12-31:00:00:00

timestamp表示的時間為1970-01-01 08:00:01到2038-01-19 11:14:07

timestamp占用的空間比datetime少,且可以設置時區等功能,所以能使用timestamp的地方盡量使用timestamp

使用timestamp還可以設置

[ON UPDATE CURRENT_TIMESTAMP]

[DEFAULT CURRENT_TIMESTAMP]

myisam和innodb支持外鍵

myisam不支持外鍵,innodb支持;

如果你使用創建外鍵的命令對myisam的表操作,操作不會返回失敗,但是是沒有外鍵關聯建立起來的。

對一個字段加減語句

經常有需求對一個字段加減會使用

update table set a = a+1

這樣是對的

但是如果這樣設置:

select a from table

取出數據后a為1

update table set a =2

這樣會導致如果在select和update之間有其他事務操作修改這個字段的話,導致最后的設置可能出錯。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM