1. 程式人生 > >數據庫學習之MySQL進階

數據庫學習之MySQL進階

對數 用戶 local fault 已提交 組合 窗口 email ability

數據庫進階

一、索引

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 120125

    倒序:
                大      小
       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進階