視圖是一個虛擬表(非真實存在),其本質是【根據SQL語句獲取動態的數據集,併爲其命名】,用戶使用時只需使用【名稱】便可獲取結果集,並能夠將其看成表來使用html
- 簡化查詢
- 能夠進行權限控制,咱們能夠把表的權限進行封閉,可是開放相應的視圖權限,視圖裏只開放部分數據
--格式:CREATE VIEW 視圖名稱 AS SQL語句 CREATE VIEW v1 AS SELET nid, name from A where nid > 4
使用視圖時,將其看成表進行操做便可,視圖和真實的表都會相互影響mysql
select * from v1
--格式:DROP VIEW 視圖名稱 DROP VIEW v1
-- 格式:ALTER VIEW 視圖名稱 AS SQL語句 ALTER VIEW v1 AS SELET A.nid, B. NAME FROM A LEFT JOIN B ON A.id = B.nid LEFT JOIN C ON A.id = C.nid WHERE A.id > 2 AND C.nid < 5
CHAR_LENGTH(str) 返回值爲字符串str 的長度,長度的單位爲字符。一個多字節字符算做一個單字符。 對於一個包含五個二字節字符集, LENGTH()返回值爲 10, 而CHAR_LENGTH()的返回值爲5。 CONCAT(str1,str2,...) 字符串拼接 若有任何一個參數爲NULL ,則返回值爲 NULL。 FORMAT(X,D) 將數字X 的格式寫爲'#,###,###.##',以四捨五入的方式保留小數點後 D 位, 並將結果以字符串的形式返回。若 D 爲 0, 則返回結果不帶有小數點,或不含小數部分。 例如: SELECT FORMAT(12332.1,4); 結果爲: '12,332.1000' INSTR(str,substr) 返回字符串 str 中子字符串的第一個出現位置。 LEFT(str,len) 返回字符串str 從開始的len位置的子序列字符。 LOWER(str) 變小寫 UPPER(str) 變大寫 LTRIM(str) 返回字符串 str ,其引導空格字符被刪除。 RTRIM(str) 返回字符串 str ,結尾空格字符被刪去。 SUBSTRING(str,pos,len) 獲取字符串子序列 LOCATE(substr,str,pos) 獲取子序列索引位置 REPEAT(str,count) 返回一個由重複的字符串str 組成的字符串,字符串str的數目等於count 。 若 count <= 0,則返回一個空字符串。 若str 或 count 爲 NULL,則返回 NULL 。 REPLACE(str,from_str,to_str) 返回字符串str 以及全部被字符串to_str替代的字符串from_str 。 REVERSE(str) 返回字符串 str ,順序和字符順序相反。 RIGHT(str,len) 從字符串str 開始,返回從後邊開始len個字符組成的子序列
delimiter \\ create function f1( i1 int, i2 int) returns int BEGIN declare num int; set num = i1 + i2; return(num); END \\ delimiter ;
drop function func_name;
# 獲取返回值 declare @i VARCHAR(32); select UPPER('alex') into @i; SELECT @i; # 在查詢中使用 select f1(11,nid) ,name from tb2;
進行數據庫應用軟件的開發時,咱們有時會碰到表中的某些數據改變,但願同時引發其餘相關數據改變的需求
利用觸發器就能知足這樣的需求,它能在表中的某些特定數據變化時自動完成相關的操做算法
當向一張表中添加或刪除記錄時,須要在相關表中進行同步操做
好比,當一個訂單產生時,訂單所購的商品的庫存量相應減小sql
當表上某列數據的值與其餘表中的數據有聯繫時
好比,當某客戶進行欠款消費,能夠在生成訂單時經過設計觸發器判斷該 客戶的累計欠款是否超出了最大限度數據庫
當須要對某張表進行跟蹤時
好比,當有新訂單產生時,須要及時通知相關人員進行處理,此時能夠在 訂單表上設計添加觸發器加以實現服務器
# 插入前 CREATE TRIGGER tri_before_insert_tb1 BEFORE INSERT ON tb1 FOR EACH ROW BEGIN ... END # 插入後 CREATE TRIGGER tri_after_insert_tb1 AFTER INSERT ON tb1 FOR EACH ROW BEGIN ... END # 刪除前 CREATE TRIGGER tri_before_delete_tb1 BEFORE DELETE ON tb1 FOR EACH ROW BEGIN ... END # 刪除後 CREATE TRIGGER tri_after_delete_tb1 AFTER DELETE ON tb1 FOR EACH ROW BEGIN ... END # 更新前 CREATE TRIGGER tri_before_update_tb1 BEFORE UPDATE ON tb1 FOR EACH ROW BEGIN ... END # 更新後 CREATE TRIGGER tri_after_update_tb1 AFTER UPDATE ON tb1 FOR EACH ROW BEGIN ... END
delimiter // CREATE TRIGGER tri_before_insert_tb1 BEFORE INSERT ON tb1 FOR EACH ROW BEGIN INSERT INTO tb2 (NAME) VALUES ('aa') END// delimiter ;注意:NEW表示即將插入的數據行,OLD表示即將刪除的數據行
DROP TRIGGER tri_after_insert_tb1;
觸發器沒法由用戶直接調用,而知因爲對錶的【增/刪/改】操做被動引起的數據結構
insert into tb1(num) values(666)
- 原子性(Atomicity),原子意爲最小的粒子,即不能再分的事務,要麼所有執行,要麼所有取消(就像上面的銀行例子)
- 一致性(Consistency):指事務發生前和發生後,數據的總額依然匹配
- 隔離性(Isolation):簡單點說,某個事務的操做對其餘事務不可見的
- 持久性(Durability):當事務完成後,其影響應該保留下來,不能撤消,只能經過「補償性事務」來抵消以前的錯誤
開啓事務(start transaction) 執行sql操做(普通sql操做) 提交/回滾(commit/rollback)
create table user( id int auto_increment primary key, name varchar(32) not null default '', money int not null default 1000 )engine=innodb charset=utf8; insert into user (name,money) values ('wangyong',1000),('liguo',1000); # 正常操做 start transaction; update user set money=1100 where name='wangyong'; updata user set money=900 where name='liguo'; # 出現異常 rollback; # 最終結果, 數據未發生變化 mysql> select * from user; +----+----------+-------+ | id | name | money | +----+----------+-------+ | 1 | wangyong | 1000 | | 2 | liguo | 1000 | +----+----------+-------+
注意:建表的時候, 選擇 innodb 引擎
購物流程中的訂單付款操做含有如下3步子操做:函數
- 從用戶的餘額中扣除訂單價格
- 在用戶的帳戶變更記錄裏記下流水
- 修改訂單狀態爲已付款
這三步需保證原子性,請用事務來控制此過程性能
索引是表的目錄,在查找內容以前能夠先在目錄中查找索引位置,以此快速定位查詢數據。對於索引,會保存在額外的文件中。大數據
設有N條記錄,若是不用索引,那平均查找N/2次,可是用了索引以後呢?通常狀況下,是以2爲底,N的對數
這塊就涉及到二叉樹的查找了
- 好處:加快了查詢的速度
- 壞處:下降了增刪改的速度,增大了表的文件大小(索引文件甚至比數據文件都還要大)
問題:大數據量進行導入別的數據表的時候,怎麼辦??
相似於字典中的目錄,如何快速找到某個字?
能夠給字典加目錄
對數據庫來講,索引的做用便是給 「數據」 加目錄
因此所謂的索引,是數據庫中專門用於幫助用戶快速查詢數據的一種數據結構
- 主鍵索引:加速查詢 + 列值惟一 + 表中只有一個(不能夠有null)
- 普通索引:僅加速查詢
- 惟一索引:加速查詢 + 列值惟一(能夠有null)
- 組合索引:多列值組成一個索引,
1. 建立表 + 索引
# 第一種: create table test( id int auto_increment primary key, name varchar(32) not null default '' )engine=innodb charset=utf8; # 第二種: create table test( id int not null default 0, name varchar(32) not null default '' )engine=innodb charset=utf8; alter table test change id id int auto_increment primary key
普通索引僅有一個功能:加速查詢
1. 建立表 + 索引
# 第一種 create table test( id int auto_increment primary key, name varchar(32) not null default '', index ix_name (name) )engine=innodb charset=utf8; # 第二種 create table test( id int auto_increment primary key, name varchar(32) not null default '' )engine=innodb charset=utf8; create index ix_name on test (name);2. 建立索引
create index index_name on table_name(column_name)3. 刪除索引
drop index_name on table_name;4. 查看索引
show index from table_name;
惟一索引有兩個功能:加速查詢 和 惟一約束(可含null)
1. 建立表 + 索引
# 第一種 create table test( id int auto_increment primary key, name varchar(32) not null default '', unique ix_name (name) )engine=innodb charset=utf8; # 第二種 create unique index 索引名稱 on 表名(name); create table test( id int auto_increment primary key, name varchar(32) not null default '' )engine=innodb charset=utf8; create unique index ix_name on test (name);2. 建立索引
create unique index 索引名 on 表名(列名)3. 刪除索引
drop unique index 索引名 on 表名
組合索引是將n個列組合成一個索引
其應用場景爲:頻繁的同時使用n列來進行查詢,如:where n1 = ‘alex’ and n2 = 666
1. 建立表 + 索引
# 建立聯合惟一索引 create unique index 索引名稱 on 表名 (name,age); create table test( id int auto_increment primary key, age int not null default 0, name varchar(32) not null default '' )engine=innodb charset=utf8; create unique index ix_name_age on test (age, name); create table in3( nid int not null auto_increment primary key, name varchar(32) not null, email varchar(64) not null, extra text )2. 建立索引
create index ix_name_email on in3(name,email);如上建立組合索引以後,查詢:
- name and email – 使用索引
- name – 使用索引
- email – 不使用索引
注意:對於同時搜索n個條件時,組合索引的性能好於多個單一索引合併
數據庫表中添加索引後確實會讓查詢速度起飛,但前提必須是正確的使用索引來查詢,若是以錯誤的方式使用,則即便創建索引也會不奏效。
即便創建索引,索引也不會生效:- like '%xx' select * from tb1 where name like '%cn'; - 使用函數 select * from tb1 where reverse(name) = 'xxx'; - 類型不一致 若是列是字符串類型,傳入條件是必須用引號引發來,否則... select * from tb1 where name = 999; - order by select email from tb1 order by name desc; 當根據索引排序時候,選擇的映射若是不是索引,則不走索引 特別的:若是對主鍵排序,則仍是走索引: select * from tb1 order by nid desc; - 組合索引最左前綴 若是組合索引爲:(name,email) name and email -- 使用索引 name -- 使用索引 email -- 不使用索引其餘注意事項
- 避免使用select * - count(1)或count(列) 代替 count(*) - 建立表時儘可能時 char 代替 varchar - 表的字段順序固定長度的字段優先 - 組合索引代替多個單列索引(常用多個條件查詢時) - 使用鏈接(JOIN)來代替子查詢(Sub-Queries) - 索引散列值(重複少)不適合建索引,例:性別不適合
使用方式:explain selext * from test;
explain selext * from test; +----+-------------+-------+-------+---------------+---------+---------+------+------+------------- | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra +----+-------------+-------+-------+---------------+---------+---------+------+------+------------- | 1 | SIMPLE | test | index | NULL | ix_name | 98 | NULL | 1 | Using index +----+-------------+-------+-------+---------------+---------+---------+------+------+-------------參數分析:
id 查詢順序標識 select_type 查詢類型 SIMPLE 簡單查詢 PRIMARY 最外層查詢 SUBQUERY 映射爲子查詢 DERIVED 子查詢 UNION 聯合 UNION RESULT 使用聯合的結果 ... table 正在訪問的表名 type 查詢時的訪問方式,性能:all < index < range < index_merge < ref_or_null < ref < eq_ref < system/const ALL 全表掃描,對於數據表從頭至尾找一遍 select * from tb1; 特別的:若是有limit限制,則找到以後就不在繼續向下掃描 select * from tb1 where email = 'xxxx@live.com' select * from tb1 where email = 'xxxx@live.com' limit 1; 雖然上述兩個語句都會進行全表掃描,第二句使用了limit,則找到一個後就再也不繼續掃描。 INDEX 全索引掃描,對索引從頭至尾找一遍 select nid from tb1; RANGE 對索引列進行範圍查找 select * from tb1 where name < 'xxx'; PS: between and in > >= < <= 操做 注意:!= 和 > 符號 REF 根據索引查找一個或多個值 select * from tb1 where name = 'xxx'; CONST 常量 表最多有一個匹配行,由於僅有一行,在這行的列值可被優化器剩餘部分認爲是常數,const表很快,由於它們只讀取一次。 select nid from tb1 where nid = 2 ; SYSTEM 系統 表僅有一行(=系統表)。這是const聯接類型的一個特例。 possible_keys 可能使用的索引 key 真實使用的 key_len MySQL中使用索引字節長度 rows mysql估計爲了找到所需的行而要讀取的行數 ------ 只是預估值 extra 該列包含MySQL解決查詢的詳細信息 「Using index」 此值表示mysql將使用索引覆蓋,以免訪問表。不要把覆蓋索引和index訪問類型弄混了。 「Using where」 這意味着mysql服務器將在存儲引擎檢索行後再進行過濾,許多where條件裏涉及索引中的列,當(而且若是)它讀取索引時,就能被存儲引擎檢驗,所以不是全部帶where子句的查詢都會顯示「Using where」。有時「Using where」的出現就是一個暗示:查詢可受益於不一樣的索引。 「Using temporary」 這意味着mysql在對查詢結果排序時會使用一個臨時表。 「Using filesort」 這意味着mysql會對結果使用一個外部索引排序,而不是按索引次序從表裏讀取行。mysql有兩種文件排序算法,這兩種排序方式均可以在內存或者磁盤上完成,explain不會告訴你mysql將使用哪種文件排序,也不會告訴你排序會在內存裏仍是磁盤上完成。刪除索引後效果
# drop 索引名稱 on 表名 drop index ix_name_age on test; mysql> explain select * from test; +----+-------------+-------+------+---------------+------+---------+------+------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+------+------+-------+ | 1 | SIMPLE | test | ALL | NULL | NULL | NULL | NULL | 1 | NULL | +----+-------------+-------+------+---------------+------+---------+------+------+-------+
日誌文件: 記錄了執行速度特別慢的SQL語句
配置MySQL自動記錄慢日誌
slow_query_log = OFF 是否開啓慢日誌記錄 long_query_time = 2 時間限制,超過此時間,則記錄 slow_query_log_file = /usr/slow.log 日誌文件
1. show variables like '%query%';
2. set global long_query_time = 1; 設置慢查詢的時間
3. set global slow_query_log = ON
4. set global slow_query_log_file = E:\program\mysql-5.6.44-winx64\data\oldboy-slow.log
SQL審計 (記錄sql的操做語句)
show variables like '%general%';