MySQL優化系列(一)--庫與表基本操作以及數據增刪改

一、操作數據語句優化認識
通常情況下,當訪問某張表的時候,讀取者首先必須獲取該表的鎖,如果有寫入操作到達,那麼寫入者一直等待讀取者完成操作(查詢開始之後就不能中斷,因此允許讀取者完成操作)。當讀取者完成對錶的操作的時候,鎖就會被解除。如果寫入者正在等待的時候,另一個讀取操作到達了,該讀取操作也會被阻塞,因爲默認的調度策略是寫入者優先於讀取者。當第一個讀取者完成操作並釋放鎖後,寫入者開始操作,並且直到該寫入者完成操作,第二個讀取者纔開始操作。
通過lock tables和unlock tables語句可以顯式地獲取或者釋放鎖,但是在通常情況下,服務器的鎖管理器會自動地在需要的時候獲取鎖,在不再需要的時候釋放鎖。獲取的鎖的類型依賴於客戶端是寫入還是讀取操作。
對某張表進行寫入操作的客戶端必須擁有獨佔的(排他的)訪問權的鎖。操作在進行的過程中,該數據表初語不一致的狀態,因爲數據記錄在刪除、添加、修改的時候,數據表上的索引也可能需要更新以相互匹配。允許兩個客戶端同時寫入一張數據表是不利的,因爲這樣的操作會很快使數據表中的信息稱爲一堆無用的數據。同時運行客戶端讀取變化之中的數據表也不正確,因爲正在讀取的位置中的數據可能正在變化(修改),讀取的結果可能並不是真實的。因此對某張表執行讀取操作的客戶端也必須獲取一個鎖,防止在讀取的過程中,其他的客戶端寫入或者改變表。但是這個鎖不需要獨佔的訪問權。因爲讀取操作不會改編數據,因此沒有理由讓某個讀取者阻止其他的讀取者訪問這張表。故讀取鎖可運行其他的客戶端在同一時刻讀取這張表。
雖然通過鎖機制可以實現多線程同時對某個表進行操作,但當某個線程作更新操作時,首先要獲得獨佔的訪問權,在更新的過程中,所有其他想要訪問這個表的線程必須要等到其更新完成爲止。此時就會導致鎖競爭問題,從而導致用戶等待時間的延長。
因此,要提高mysql的更新/插入效率,應首先考慮降低鎖的競爭,減少寫操作的等待時間。
二、insert語句
優化:
(1)當我們需要批量插入數據的時候,可以同時插入多條(大概10條同時插入是最高效的)。
例如:INSERT INTO score (change_type,score,user_id) VALUES ('吃飯',10,1),('喝茶',10,1),('喝茶',10,1);
(2)將進程/線程數控制在2倍於CPU數據相對合適
(3)採用順序主鍵策略(例如自增主鍵,或者修改業務邏輯,讓插入的記錄儘可能順序主鍵)
(4)考慮使用replace語句代替insert語句
三、delete語句
mysql中truncate table和delete語句都可以刪除表裏面所有數據,但是在一些情況下有些不同。
(1)、truncate table速度要更快一些,但是truncate刪除後不記錄mysql日誌,不可以恢復數據
(2)、如果沒有外鍵關聯,innodb執行truncate是先drop table(原始表),再創建一個跟原始表一樣的空表,速度要遠遠快於delete逐條刪除行記錄
(3)、如果使用innodb_file_per_table參數:truncate table能重新利用釋放的硬盤空間,在innodb plugin中,truncate table爲自動回收,如果不用innodb plugin,那麼需要使用optimize table來優化表,釋放空間。
truncate table刪除表後,optimize table尤其重要,特別是大數據數據庫,表空間可以得到釋放!
(4)表有外鍵關聯,truncate table刪除表數據爲逐行刪除
如果外鍵指定級聯刪除,關聯的字表也會被刪除所有表數據。如果外鍵未指定級聯,truncate table逐行刪除數據,如果是父行關聯字表行數據,將會報錯。
(5)auto_increment計數器在truncate table後會重置爲0,與是否有外鍵關聯沒有關係
一個大的delete或者insert操作,要非常小心,因爲這兩個操作是會鎖表的,表一鎖住,其他操作就進不來了。因此,我們要交給DBA去拆分,重整數據庫策略,比如限制處理1000條。
刪除數據的速度和創建的索引數量成正比的。所以在超大型數據庫中,刪除時處理好索引關係非常重要。推薦的這種方法:在刪除數據之前刪除這幾個索引,然後刪除其中無用數據,刪除完成後重新創建索引。
四、update語句
(1)儘量不要修改主鍵字段;
(2)當修改varchar型字段時,儘量使用相同長度內容的值代替;
(3)儘量最小化對於含有update觸發器的表的update操作
(4)避免update將要複製到其他數據庫的列
(5)避免update建有很多索引的列
(6)避免update在where自居條件中的列
五、replace語句
根據實際情況可以使用replace語句代替insert/update語句
例如:如果一個表在一個字段上建立了唯一索引,當向這個表中使用已經存在的鍵值插入一條記錄,將會拋出一個主鍵衝突的錯誤。如果我們想用新記錄的值來覆蓋原來的記錄值時,就可以使用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)
1
2
3
4
此語句的作用是向表table中插入3條記錄。如果主鍵id爲1或2不存在就相當於插入語句:

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

如果存在相同的值則不會插入數據。

(2)replace(object, search, replace),把object中出現search的全部替換爲replace。
//用法一:並不是修改數據,而只是單純做局部替換數據返還而已。

SELECT REPLACE('喝茶','茶','喝')

//結果: 喝喝
用法二:修改表數據啦,對應下面就是,根據change_type字段找到做任務的數據,用bb來替換

UPDATE score SET change_type=REPLACE(change_type,'做任務','bb')
在此,做下對比:UPDATE和REPLACE的區別:

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

2)UPDATE可以選擇性地更新記錄的一部分字段。而REPLACE在發現有重複記錄時就將這條記錄徹底刪除,再插入新的記錄。也就是說,將所有的字段都更新了。
其實REPLACE更像INSERT與DELETE的結合。
六、庫與表基本操作
(一)庫的基本操作
(1)查看所有數據庫以及使用數據庫

show databases; 
use table;

(2)查看當前數據庫

select database(); 

(3)顯示當前時間、用戶名、數據庫版本

select now(), user(), version(); 

(4)創建庫

create database[ if not exists] 數據庫名 數據庫選項
    數據庫選項:
 

   CHARACTER SET charset_name
    COLLATE collation_name 

(5)查看當前庫信息

show create database 數據庫名

(6)修改庫的選項信息

alter database 庫名 選項信息

(7)刪除庫

drop database[ if exists] 數據庫名
同時刪除該數據庫相關的目錄及其目錄內容
二)表的基本操作
(1)創建表:

create [temporary] table[ if not exists] [庫名.]表名 ( 表的結構定義 )[ 表選項]
        每個字段必須有數據類型
        最後一個字段後不能有逗號
        temporary 臨時表,會話結束時表自動消失
        對於字段的定義:
            字段名 數據類型 [NOT NULL | NULL] [DEFAULT default_value] [AUTO_INCREMENT] [UNIQUE [KEY] | [PRIMARY] KEY] [COMMENT 'string'] 

(2)表的選項:
[1]刪除列

ALTER TABLE 【表名字】 DROP 【列名稱】

[2]增加列

ALTER TABLE 【表名字】 ADD 【列名稱】 INT NOT NULL COMMENT ‘註釋說明’

[3]修改列的類型信息

ALTER TABLE 【表名字】 CHANGE 【列名稱】【新列名稱(這裏可以用和原來列同名即可)】 BIGINT NOT NULL COMMENT ‘註釋說明’

[4]重命名列

ALTER TABLE 【表名字】 CHANGE 【列名稱】【新列名稱】 BIGINT NOT NULL COMMENT ‘註釋說明’

[5]重命名錶

ALTER TABLE 【表名字】 RENAME 【表新名字】

[6]刪除表中主鍵

Alter TABLE 【表名字】 drop primary key

[7]添加主鍵

ALTER TABLE sj_resource_charges ADD CONSTRAINT PK_SJ_RESOURCE_CHARGES PRIMARY KEY (resid,resfromid)

[8]添加索引

ALTER TABLE sj_resource_charges add index INDEX_NAME (name);

[9]添加唯一限制條件索引

ALTER TABLE sj_resource_charges add unique emp_name2(cardnumber);

[10]刪除索引

Alter table tablename drop index emp_name;

(3)查看所有表

SHOW TABLES;

(4)查看錶機構:

SHOW CREATE TABLE 表名    (信息更詳細)
    DESC 表名 / DESCRIBE 表名 / EXPLAIN 表名 / SHOW COLUMNS FROM 表名 [LIKE 'PATTERN']
    SHOW TABLE STATUS [FROM db_name] [LIKE 'pattern']

(5)修改表:對錶進行重命名

RENAME TABLE 原表名 TO 新表名
        RENAME TABLE 原表名 TO 庫名.表名    (可將表移動到另一個數據庫)
        -- RENAME可以交換兩個表名

(6)刪除表
DROP TABLE[ IF EXISTS] 表名

(7)清空表數據

TRUNCATE [TABLE] 表名

(8)複製表結構

CREATE TABLE 表名 [AS] SELECT * FROM 要複製的表名
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章