數據庫學習之MySQL進階
數據庫進階
一、索引
1.索引簡介
索引在MySQL中也叫做“鍵”,是存儲引擎用於快速找到記錄的一種數據結構。索引對於良好的性能非常關鍵,尤其是當表中的數據量越來越大時,索引對於性能的影響愈發重要。
索引優化應該是對查詢性能優化最有效的手段了。
索引能夠輕易將查詢性能提高好幾個數量級。
索引相當於字典的音序表,如果要查某個字,如果不使用音序表,則需要從幾百頁中逐頁去查。
索引特點:創建與維護索引會消耗很多時間與磁盤空間,但查詢速度大大提高!
2.創建索引語法
--創建表時
CREATE TABLE 表名 (
字段名1 數據類型 [完整性約束條件…],
字段名2 數據類型 [完整性約束條件…],
[UNIQUE | FULLTEXT | SPATIAL ] INDEX | KEY
[索引名] (字段名[(長度)] [ASC |DESC])
);
實例:
CREATE TABLE test2(
id INT,
name VARCHAR(20),
INDEX index_name (name)
);
--添加索引
---CREATE在已存在的表上創建索引 CREATE [UNIQUE | FULLTEXT | SPATIAL ] INDEX 索引名 ON 表名 (字段名[(長度)] [ASC |DESC]) ; ---ALTER TABLE在已存在的表上創建索引 ALTER TABLE 表名 ADD [UNIQUE | FULLTEXT | SPATIAL ] INDEX 索引名 (字段名[(長度)] [ASC |DESC]) ; CREATE INDEX index_emp_name on emp1(name); ALTER TABLE emp2 ADD UNIQUE INDEX index_bank_num(band_num);
-- 刪除索引
語法:DROP INDEX 索引名 on 表名
DROP INDEX index_emp_name on emp1;
DROP INDEX bank_num on emp2;
3.索引測試實驗
--創建表 create table t1(id int,name varchar(20)); --存儲過程 delimiter $$ create procedure autoinsert() BEGIN declare i int default 1; while(i<5000)do insert into t1 values(i,‘yuan‘); set i=i+1; end while; END$$ delimiter ; --調用函數 call autoinsert(); -- 花費時間比較: -- 創建索引前 select * from t1 where id=300000;--0.32s -- 添加索引 create index index_id on t1(id); -- 創建索引後 select * from Indexdb.t1 where id=300000;--0.00s --刪除索引 drop index index_id on t1;
實驗二:
use crawed;
desc doutula;
select count(*) from doutula;
+----------+
| count(*) |
+----------+
| 27308 |
+----------+
select name from doutula where name like ‘%壞蛋%‘;
--34 rows in set (0.53 sec)
create index index_name on doutula (name);
select name from doutula where name like ‘%壞蛋%‘;
--34 rows in set (0.05 sec)
4.正確使用索引
數據庫表中添加索引後確實會讓查詢速度起飛,但前提必須是正確的使用索引來查詢,如果以錯誤的方式使用,則即使建立索引也會不奏效。
即使建立索引,索引也不會生效:
- like ‘%xx‘ select * from tb1 where name like ‘%cn‘; - 使用函數 select * from tb1 where reverse(name) = ‘wupeiqi‘; - or select * from tb1 where nid = 1 or email = ‘[email protected]‘; 特別的:當or條件中有未建立索引的列才失效,以下會走索引 select * from tb1 where nid = 1 or name = ‘seven‘; select * from tb1 where nid = 1 or email = ‘[email protected]‘ and name = ‘alex‘ - 類型不一致 如果列是字符串類型,傳入條件是必須用引號引起來,不然... select * from tb1 where name = 999; - != select * from tb1 where name != ‘alex‘ 特別的:如果是主鍵,則還是會走索引 select * from tb1 where nid != 123 - > select * from tb1 where name > ‘alex‘ 特別的:如果是主鍵或索引是整數類型,則還是會走索引 select * from tb1 where nid > 123 select * from tb1 where num > 123 - order by select email from tb1 order by name desc; 當根據索引排序時候,選擇的映射如果不是索引,則不走索引 特別的:如果對主鍵排序,則還是走索引: select * from tb1 order by nid desc; - 組合索引最左前綴 如果組合索引為:(name,email) name and email -- 使用索引 name -- 使用索引 email -- 不使用索引View Code
二、limit分頁
每頁顯示10條: 當前 118 120, 125 倒序: 大 小 970 7 6 6 5 54 43 32 19 98 下一頁: select * from tb1 where nid < (select nid from (select nid from tb1 where nid < 當前頁最小值 order by nid desc limit 每頁數據 *【頁碼-當前頁】) A order by A.nid asc limit 1) order by nid desc limit 10; select * from tb1 where nid < (select nid from (select nid from tb1 where nid < 970 order by nid desc limit 40) A order by A.nid asc limit 1) order by nid desc limit 10; 上一頁: select * from tb1 where nid < (select nid from (select nid from tb1 where nid > 當前頁最大值 order by nid asc limit 每頁數據 *【當前頁-頁碼】) A order by A.nid asc limit 1) order by nid desc limit 10; select * from tb1 where nid < (select nid from (select nid from tb1 where nid > 980 order by nid asc limit 20) A order by A.nid desc limit 1) order by nid desc limit 10;View Code
三、Python關於MySQL的API接口-pymysql模塊
pymsql是Python中操作MySQL的模塊,其使用方法和py2的MySQLdb幾乎相同。
安裝:pip install pymysql
代碼:
# -*- coding: utf-8 -*-
import pymysql
#1.連接mysql
conn = pymysql.connect(host=‘localhost‘,port=3306,user=‘root‘,password=‘0000‘,db=‘python3‘)
# conn = pymysql.connect(host=‘localhost‘,user=‘root‘,password=‘0000‘,db=‘crawed‘,charset=‘utf8‘,cursorclass = pymysql.cursors.DictCursor,use_unicode=True)
#2.創建遊標
cursor = conn.cursor()
# cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) #更改獲取數據結果的數據類型
#3.創建表添加數據
# sql = ‘create table test(id int,name varchar(20))‘
# sql1 = "insert into test values (1,‘zhang‘),(2,‘fei‘);"
# cursor.execute(sql)
# cursor.execute(sql1)
#4.查詢數據
sql2 = ‘select * from test;‘
cursor.execute(sql2)
# num = cursor.fetchone()
# print(cursor.fetchone())
# print(cursor.fetchmany(2))
print(cursor.fetchall())
#5.scroll 控制遊標位置
# print(cursor.fetchone())
# print(cursor.fetchone())
# cursor.scroll(-1,mode=‘relative‘) # 相對當前位置移動
# cursor.scroll(0,mode=‘absolute‘) # 相對絕對位置移動
# print(cursor.fetchone())
conn.commit()
conn.close()
四、事務
事務指邏輯上的一組操作,組成這組操作的各個單元,要不全部成功,要不全部不成功。
數據庫開啟事務命令
-- start transaction 開啟事務
-- Rollback 回滾事務,即撤銷指定的sql語句(只能回退insert delete update語句),回滾到上一次commit的位置
-- Commit 提交事務,提交未存儲的事務
-- savepoint 保留點 ,事務處理中設置的臨時占位符 你可以對它發布回退(與整個事務回退不同)
轉賬實例:
select * from test;
+------+-------+--------+
| id | name | salary |
+------+-------+--------+
| 1 | zhang | 8000 |
| 2 | fei | 10000 |
| 3 | kobe | 8000 |
| 4 | james | 9000 |
+------+-------+--------+
4 rows in set (0.00 sec)
start transaction;
update test set salary=salary-5000 where id=2;
rollback;
update test set salary=salary-5000 where id=2;
update test set salary=salary+5000 where id=1;
commit;
savepoint
create table test2(id int PRIMARY KEY auto_increment,name VARCHAR(20)) engine=innodb;
INSERT INTO test2(name) VALUE ("alvin"),
("yuan"),
("xialv");
start transaction;
insert into test2 (name)values(‘silv‘);
select * from test2;
commit;
-- 保留點
start transaction;
insert into test2 (name)values(‘wu‘);
savepoint insert_wu;
select * from test2;
delete from test2 where id=4;
savepoint delete1;
select * from test2;
delete from test2 where id=1;
savepoint delete2;
select * from test2;
rollback to delete1;
select * from test2;
savepoint
事務特性
<1> 原子性(Atomicity):原子性是指事務是一個不可分割的工作單位,事務中的操作要麽都發生,要麽都不發生。 <2> 一致性(Consistency):事務前後數據的完整性必須保持一致。在事務執行之前數據庫是符合數據完整性約束的,無論事務是否執行成功,事務結束後的數據庫中的數據也應該是符合完整性約束的。在某一時間點,如果數據庫中的所有記錄都能保證滿足當前數據庫中的所有約束,則可以說當前的數據庫是符合數據完整性約束的。 比如刪部門表前應該刪掉關聯員工(已經建立外鍵),如果數據庫服務器發生錯誤,有一個員工沒刪掉,那麽此時員工的部門表已經刪除,那麽就不符合完整性約束了,所以這樣的數據庫也就性能太差啦! <3>隔離性(Isolation):事務的隔離性是指多個用戶並發訪問數據庫時,一個用戶的事務不能被其它用戶的事務所幹擾,多個並發事務之間數據要相互隔離。 <4>持久性(Durability):持久性是指一個事務一旦被提交,它對數據庫中數據的改變就是永久性的,接下來即使數據庫發生故障也不應該對其有任何影響。
四個隔離級別:
Serializable:可避免臟讀、不可重復讀、虛讀情況的發生。(串行化)
Repeatable read:可避免臟讀、不可重復讀情況的發生。(可重復讀)不可以避免虛讀
Read committed:可避免臟讀情況發生(讀已提交)
Read uncommitted:最低級別,以上情況均無法保證。(讀未提交)
安全性考慮:Serializable>Repeatable read>Read committed>Read uncommitted
數據庫效率:Read uncommitted>Read committed>Repeatable read>Serializable
一般情況下,我們會使用Repeatable read、Read committed mysql數據庫默認的數據庫隔離級別Repeatable read
mysql中設置數據庫的隔離級別語句:set
[
global
/session]
transaction
isolation
level
xxxx;
如果使用global則修改的是數據庫的默認隔離級別,所有新開的窗口的隔離級別繼承自這個默認隔離級別如果使用session修改,則修改的是當前客戶端的隔離級別,和數據庫默認隔離級別無關。當前的客戶端是什麽隔離級別,就能防止什麽隔離級別問題,和其他客戶端是什麽隔離級別無關。
mysql中設置數據庫的隔離級別語句:select
@@tx_isolation;
數據庫學習之MySQL進階