目錄
http://blog.csdn.net/yongchao940/article/details/55266603
4.2 replace into與 insert into ... on duplicate key update
1 分區及分表
http://blog.csdn.net/yongchao940/article/details/55266603
1.1 橫向分區與縱向分區
橫向:記錄分
縱向:字段分
1.2 分區的內在涵義
1.2.1 分區意義
首先MYISAM、InnoDB都是支持分區的。
1. 表非常大以至於無法全部都放到內存,或者只在表的最後部分有熱點數據,其他均爲歷史數據
2. 分區表數據更容易維護(可獨立對分區進行優化、檢查、修復及批量刪除大數據可以採用drop分區的形式等)
3. 分區表的數據可以分佈在不同的物理設備上,從而高效地利用多個硬件設備
4. 分區表可以避免某些特殊的瓶頸(ps: InnoDB的單個索引的互斥訪問、ext3文件系統的inode鎖競爭等) 5、可以備份和恢復獨立的分區,非常適用於大數據集的場景、
5. 進行大數據搜索的時候可以進行並行處理
6. 跨多個磁盤分散數據查詢,來獲得更大的查詢吞吐量。
1.2.2 分區物理存儲
對應MySQL三個文件的具體情況.
分區在邏輯上是一個表,但是實際上卻可以由多個物理分區組成。在執行查詢的時候,和優化器會根據分區定義過濾出我們需要數據的分區,無須全表掃描。刪除數據的時候同樣的道理,效率也是非常的高。
1.3 分區的常見語句及注意事項
1.3.1 注意事項
http://lobert.iteye.com/blog/1955841
http://www.simlinux.com/2014/08/19/mysql-partitions.html
範圍分區添加分區只能在最大值後面追加分區
比如 現在已經有了如下分區
|
|
---|---|
p0 |
5 |
p1 |
10 |
p2 |
15 |
1. 分區值必須是嚴格遞增的。如上圖,那麼插入 alter table orders_range add partition(partition p3 values less than (12));是無法插入成功的。
因此如果我們在程序中有 alter table orders_range add partition(partition p3 values less than MAXVALUE);
2. 此時需要添加分區,需要先刪除max對應的分區,然後再添加我們需要的分區
3. 如果我們最後一個分區是[10,15),那麼我們插入的值>=15都是插入不進去的,會報錯。
4. 所有分區的engine必須一樣
5. 分區間隔必須是int,分區名稱不能以數字開頭 這個導致我們ETL中 preload刪除分區無法形成這種語法。只能借用delete刪除數據
6. less than 表示分割區間是 [ )形式
7. 如果表上有主鍵或唯一索引列,range方式分區必須加入 https://www.zhihu.com/question/21738216
每個分區值上都有獨立的索引。 一般原則就是分區列必作爲索引。
分區表的索引只是在各個底層表各自加上一個完全相同的索引。之於存儲引擎,分區表的底層表與普通表沒有區別。
8. null對分區主鍵的影響?
9 MySQL中插入換行
直接插入\n 或者通過char(13)的形式,
一般比如 concat_ws('\n',a,b,c)或者 concat_ws(char(13),a,b,c)
1.3.2 分區操作
1 查看分區
代碼塊
Plain Text
SELECT PARTITION_NAME,TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME = 'table_name';
2 添加分區
代碼塊
Plain Text
alter table orders_range add partition(partition p5 values less than (25));alter table orders_range add partition(partition p5 values less than MAXVALUE);
note:在create語句中沒有進行分區的相關定義,也可以可以添加分區的。
代碼塊
Plain Text
*可以對現有表進行分區,並且會按規則自動的將表中的數據分配相應的分區
中,這樣就比較好了,可以省去很多事情,看下面的操作*/
mysql> alter table aa partition by RANGE(id)
-> (PARTITION p1 VALUES less than (1),
-> PARTITION p2 VALUES less than (5),
-> PARTITION p3 VALUES less than MAXVALUE);
Query OK, 15 rows affected (0.21 sec) //對15數據進行分區
Records: 15 Duplicates: 0 Warnings: 0
3 刪除分區
note: 批量刪除分區
alter table xx drop drop partition p17177,p17178;
這種帶有數字的直接用Excel拖動生成就行了
note:
多表記錄級聯刪除,在一些orm中直接配置級聯就可以刪除,單純的數據庫而言也是可以的
DELETE FROM tablename [WHERE CONDITION]
delete from emp where ename='dony';
一次刪除多個表的數據,語法如下:
delete t1,t2 from table_name as t1 left join table2_name as t2 on t1.id=t2.id where table_name.id=25
4 其他操作
1.4 分區和索引
從本質來說就是兩個東西,沒有什麼本質的關係
但是從效果來說,都能加快查詢的速度。但是在修改表(包括但不限於刪除)層面上,分區的效率優勢就體現出來了。尤其是在表非常大的情況下。
##
1.5 MySQL分表
1.5.1 分表和分區的區別
http://blog.51yip.com/mysql/949.html
1.5.2 索引
1 首先連接字段,在連接的兩個表中的字段類型一致比不一致效率高一點,但是不明顯,最起碼在200w數據量的情況下是不明顯的。 note: in(23,225)這種情況就會走range索引
2 count(*)比sum(*)的效率高一點,但是在200w+數據量的情況下只有0.0xs的優勢,也是很不明顯
3 複合主鍵在索引層面,就相當於聯合索引,也是符合在最左前綴原則
4 索引失效情況
### 從左到右,遇到範圍查詢即索引失效(in不包括在內)。
範圍查詢其實可以做進一步的細化區分,in更加細化的描述應該是多值精確匹配, between則是範圍查詢。
### 隱式類型轉換
mysql隱士類型轉換坑較多,不要使用隱士類型轉換。
note:隱式類型轉換還有一個查詢匹配的大坑
當字段是string類型的時候,查詢條件爲 int 0的時候,會匹配上字段中以字符開頭的記錄
關於隱式轉換的規則,
-
當查詢字段是INT類型,如果查詢條件爲CHAR,將查詢條件轉換爲INT,如果是字符串前導都是數字將會進行截取,如果不是轉換爲0。
-
當查詢字段是CHAR類型,如果查詢條件爲INT,將查詢字段爲換爲INT再進行比較,可能會造成全表掃描。示例2的name字段爲CHAR類型,第一句查詢轉換爲INT時都等於0,所以全部匹配了;第二句查詢同爲CHAR類型不發生轉換,所以僅匹配值爲0的記錄。
https://blog.eood.cn/mysql_params
2 binlog
2.1 binlog
2.1.1 日誌文件
http://www.cnblogs.com/martinzhang/p/3454358.html
MySQL的二進制日誌記錄了所有的DDL和DML(除了數據查詢語句)語句,以事件形式記錄,
還包含語句所執行的消耗的時間,MySQL的二進制日誌是事務安全型的。
一般來說開啓二進制日誌大概會有1%的性能損耗(參見MySQL官方中文手冊 5.1.24版)。
二進制有兩個最重要的使用場景:
其一:MySQL Replication在Master端開啓binlog,Mster把它的二進制日誌傳遞給slaves來達到master-slave數據一致的目的。
其二:自然就是數據恢復了,通過使用mysqlbinlog工具來使恢復數據。 二進制日誌包括兩類文件:二進制日誌索引文件(文件名後綴爲.index)用於記錄所有的二進制文件,二進制日誌文件(文件名後綴爲.00000*)記錄數據庫所有的DDL和DML(除了數據查詢語句)語句事件。
2.1.2 日誌文件的擴展
當停止或重啓時,服務器會把日誌文件記入下一個日誌文件,Mysql會在重啓時生成一個新的日誌文件,文件序號遞增,此外,如果日誌文件超過max_binlog_size系統變量配置的上限時,也會生成新的日誌文件。
2.1.3 日誌文件的查看
Mysql提供了mysqlbinlog命令來查看日誌文件,如mysqlbinlog xxx-bin.001 | more。在記錄每條變更日誌的時候,日誌文件都會把當前時間給記錄下來,以便進行數據庫恢復。
2.1.4 日誌文件格式
statement格式簡單來說會記錄下執行的SQL語句,爲了保證日誌能夠恢復或者同步數據,在記錄下執行SQL的過程中,還必須記錄下上下文環境。但並不是所有的語句statement都能記錄,比如udf,沒有使用order by的limit 還有其他的一些函數和存儲過程。
但是隻記錄執行的sql語句,一般在整表修改或者alter的時候數據量會比row格式小得多
row格式會記錄下變更後的數據,但是不用記錄上下文。詳細記錄了數據修改細節。因爲如果碰到alter Table之類的語句會導致所有修改後的記錄都會被記錄(包括沒有修改的列),導致日誌數據量非常大。但是不用記錄
http://www.cnblogs.com/kevingrace/p/6065088.html
note:公司的許多庫使用的都是statement。
MySQL 5.7.7 之後默認格式是row之前使用的是statement。
2.2 binlog開啓
https://xcoder.in/2015/08/10/mysql-binlog-try/
http://www.cnblogs.com/EasonJim/p/7158466.html
http://blog.5ibc.net/p/122608.html
http://www.jianshu.com/p/2c8325f0d393
2.3 binlog試用
使用mysql bin目錄下的mysqlbinlog命令查看bin ./mysqlbinlog /usr/local/var/mysql/mysql-bin.000001文件,如下圖所示
2.4 實踐
2.4.1 max_binlog_cache_size溢出
http://liuqunying.blog.51cto.com/3984207/1751687
https://my.oschina.net/u/2485991/blog/533123
note:
max_binlog_size 一般設置爲512M或1GB,但不能超過1GB。該設置不能嚴格控制Binlog的大小,尤其是Binlog遇到比較大的事務時,爲了保證事務的完整性,不可能做切換日誌的動作,只能將該事務的所有SQL都記錄進當前日誌,直到事務結束。這種情況下回出現日誌文件大小超過設定值的情況。
binlog_cache_size 這個默認32k,公司裏有1m的也有64M的
max_binlog_cache_size 一個線程來了會按照binlog_cache_size分配cache,不夠的會用臨時文件,對於一個多事務的任務,max_binlog_cache_size會控制所有的事務總的binlog_cache_size的大小。這個值不會超過4G
show variables like '%binlog_size%'; 該命令查出來的大小的值的單位是bytes
http://blog.csdn.net/m48o8gewuc/article/details/72888092
2.4.2 在row模式下查看原生sql
公司的show variables like 'binlog_rows_query_log_events';也是打開的
http://blog.csdn.net/mchdba/article/details/52268615
2.4.3 業務庫大表在線修改表結構:
基本原理是生成中間表,複製數據,最後刪除中間表。中間的過程並不總是會複製數據,如果複製數據會導致非常耗時,極有可能會導致鎖表。
具體過程??
3 鎖
可以從引擎和讀/寫/行/表 這兩個維度來對MySQL的鎖進行分析。
redo&undo https://my.oschina.net/guol/blog/156682
4 基本操作
4.1 修改字段列排序
字段增加和修改語法(ADD/CNAHGE/MODIFY)中,都有一個可選項 first|after
column_name,這個選項可以用來修改字段在表中的位置,默認 ADD 增加的新字段是加在表的最後位置,而 CHANGE/MODIFY 默認都不會改變字段的位置。
alter table emp add birth date after ename; (alter table emp add birth date after ename,add hah after birth,add hab after hah;)可以一次增加多個列指定順序。
alter table emp modify age int(3) first; 修改字段 age,將它放在最前面
查詢順序? 不帶任何限制的查詢,
https://www.zhihu.com/question/19726583
這種有很多影響因素,一般結果會是查詢順序,但是不能依賴於這個(並不一定總是查詢順序)。
字段增加和修改語法(ADD/CNAHGE/MODIFY)中,都有一個可選項 first|after
column_name,這個選項可以用來修改字段在表中的位置,默認 ADD 增加的新字段是加在表的最後位置,而 CHANGE/MODIFY 默認都不會改變字段的位置。
alter table emp add birth date after ename;
alter table emp modify age int(3) first; 修改字段 age,將它放在最前面
4.2 replace into與 insert into ... on duplicate key update
replace into 相當於有重複key的情況下,會先刪除舊的記錄,然後添加一條新的記錄。沒有replace的字段則會以默認值填充。
insert into on....則是隻會修改涉及的字段,沒有涉及修改的字段還是保留原記錄的內容。
http://blog.csdn.net/mchdba/article/details/8647560
5 存儲
5.1之後就是compact格式,
-
減少了大約20%的空間
-
在某些操作下會增加CPU的佔用
-
在典型的應用場景下,比Redundant快
compress用在varchar特別長,或者blob資源比較多的場景。
6. 問題
mysql不支持正則替換功能,
不支持刪除分區的非等
不支持窗口函數,但是MySQL有自己的語法來實現窗口功能。
建表語句:auto_increament=xx 表示自增數字的起點