1.什麼是索引 ?-- 目錄html
索引就是創建起的一個在存儲表階段就有的一個存儲結構,能在查詢的時候加速。python
2.索引的重要性:mysql
讀寫比例 爲 10:1,全部讀(查詢)的速度就相當重要了。android
3.索引的原理:ios
block 磁盤預讀原理sql
至關於讀文件操做的 :for line in f數據庫
每一個索引塊能夠存4096個字節安全
讀硬盤的io操做的時間很是的長,比CPU執行指令的時間長不少,儘可能的減小IO次數纔是讀寫數據的主要要解決的問題。服務器
1.數據庫的存儲方式:session
1.新的數據結構 —— 樹
缺點:容易出現數據只在一端,形成讀取慢(io操做次數多)。
2.平衡樹 balance tree - b樹
缺點:存儲的數據長度大、能存儲的數據條數有限,形成書的高度比較大,讀取效率很低。
3.在b樹的基礎上進行了改良 - b+樹
4.mysql當中全部的b+樹索引的高度都基本控制在3層:
5.什麼會影響索引的效率? —— 樹的高度
在innodb中 :彙集索引和輔助索引並存的
彙集索引 - 主鍵 、更快
只有主鍵是彙集索引
數據直接存儲在樹結構的葉子節點
輔助索引 - 除了主鍵以外全部的索引都是輔助索引 、稍慢
數據不直接存儲在樹中
在myisam中 :只有輔助索引,沒有彙集索引
1.索引的種類:
primary key 主鍵 ,是彙集索引 ,約束的做用:非空 + 惟一
聯合主鍵
unique 自帶索引 ,是輔助索引 ,約束的做用:惟一
聯合惟一
index 是輔助索引,沒有約束做用
聯合索引
注意:按大項分有三個種類:primary key 、unique 、index
細分有6個種類:primary key 、聯合主鍵 、unique 、聯合惟一 、index 、聯合索引
2.看一下如何建立索引、建立索引以後的變化
create index 索引名字 on 表(字段)
刪除索引 :drop index 索引名 on 表名字;
3.索引是如何發揮做用的?
select * from 表 where id = xxxxx;
1.索引不生效的緣由:
<1.>要查詢的數據的範圍大
與範圍相關的:
1.< >= <= !=(!=幾乎命中不了索引)
2.between and
select * from 表 order by age limit 0,5;
select * from 表 where id between 1000000 and 1000005;
3.like
<2.>若是一列內容的區分度不高,索引也不生效
<3.>索引列不能在條件中參與計算
<4.>對兩列內容進行條件查詢
and :and條件兩端的內容,優先選擇一個有索引的,而且樹形結構更好的,來進行查詢(效率也會更高)。兩個條件都成立才能完成where條件,先完成範圍小的,縮小後面條件的壓力。
or :帶or條件的,不會進行優化,只是根據條件從左到右依次篩選。
條件中帶有or的要想命中索引,這些條件中全部的列都是索引列。
<5.>聯合索引
建立聯合索引:create index ind_mix on s1(id,name,email);
select * from s1 where id =1000000 and email = 'eva1000000@oldboy'; 能命中索引
1.在聯合索引中若是使用了or條件索引就不能生效:
select * from s1 where id =1000000 or email = 'eva1000000@oldboy'; 不能命中索引
2.最左前綴原則 :在聯合索引中,條件必須含有在建立索引的時候的第一個索引列。
select * from s1 where id =1000000; 能命中索引 select * from s1 where email = 'eva1000000@oldboy'; 不能命中索引 # 聯合索引 (a,b,c,d) a,b 、 a,c 、 a 、 a,d 、 a,b,d 、 a,c,d 、 a,b,c,d # 等含有a索引的都能命中索引 # 不含a索引的其餘索引都不能命中。
3.在整個條件中,從開始出現模糊匹配的那一刻,索引就失效了
select * from s1 where id >1000000 and email = 'eva1000001@oldboy'; 不能命中索引 select * from s1 where id =1000000 and email like 'eva%'; 能命中引
2.何時用聯合索引?
3.對於單列的索引:
4.使用or來鏈接多個條件:
1.覆蓋索引
若是咱們使用索引做爲條件查詢,查詢完畢以後,不須要回表查,就是覆蓋索引。
explain select id from s1 where id = 1000000;
explain select count(id) from s1 where id > 1000000;
2.合併索引
對兩個字段分別建立索引,因爲sql的條件讓兩個索引同時生效了,那麼這個時候這兩個索引就成爲了合併索引
3.執行計劃 explain
若是你想在執行sql語句以前就知道sql語句的執行狀況,那麼可使用執行計劃。
# 狀況1: 若是有30000000條數據,使用sql語句查詢須要20s, explain sql語句 --> 並不會真正的執行sql,而是會給你列出一個執行計劃 # 狀況2: 20條數據 --> 30000000 explain sql
4.建議
<1>建表、使用sql語句的時候注意的:
<2> utf8 與 utf8mb4 :
之後若是遇到使用 utf8 出現亂碼的狀況,能夠更改成 utf8mb4 進行編碼。
1.where條件單表查,鎖定最小返回記錄表。這句話的意思是把查詢語句的where都應用到表中返回的記錄數最小的表開始查起,單表每一個字段分別查詢,看哪一個字段的區分度最高
2.explain查看執行計劃,是否與第1步預期一致(從鎖定記錄較少的表開始查詢)
3.order by limit 形式的sql語句讓排序的表優先查
4.瞭解業務方使用場景
5.加索引時參照建索引的幾大原則
6.觀察結果,不符合預期繼續從0分析
1.慢日誌
2.配置:
內存
show variables like '%query%';
show variables like '%queries%';
set global 變量名 = 值
配置文件
mysqld --defaults-file='E:\wupeiqi\mysql-5.7.16-winx64\mysql-5.7.16-winx64\my-default.ini'
my.conf內容:
注意:修改配置文件以後,須要重啓服務
3.日誌管理
詳見網址:https://www.cnblogs.com/Eva-J/articles/10126413.html#_label8
python至關因而客戶端
import pymysql conn = pymysql.connect(host='127.0.0.1', user='root', password="123",database='day40') # python與mysql鏈接 cur = conn.cursor() # 建立 數據庫操做符:遊標 # 增長數據 cur.execute('insert into employee(emp_name,sex,age,hire_date) ' 'values ("郭凱豐","male",40,20190808)') # 刪除數據 cur.execute('delete from employee where id = 18') conn.commit() # 提交 conn.close() # 查詢數據 import pymysql conn = pymysql.connect(host='127.0.0.1', user='root', password="123",database='day40') cur = conn.cursor(pymysql.cursors.DictCursor) # 想要輸出爲字典格式時加上pymysql.cursors.DictCursor cur.execute('select * from employee where id > 10') ret = cur.fetchone() # 查詢第一條數據 print(ret['emp_name']) ret = cur.fetchmany(5) # 查詢5條數據 ret = cur.fetchall() # 查詢全部的數據 print(ret) conn.close()
1.數據庫的邏輯備份
語法:mysqldump -h 服務器 -u用戶名 -p密碼 數據庫名 > 備份文件.sql
#示例: #單庫備份 mysqldump -uroot -p123 db1 > db1.sql mysqldump -uroot -p123 db1 table1 table2 > db1-table1-table2.sql #多庫備份 mysqldump -uroot -p123 --databases db1 db2 mysql db3 > db1_db2_mysql_db3.sql #備份全部庫 mysqldump -uroot -p123 --all-databases > all.sql
2.數據恢復
#方法一: [root@egon backup]# mysql -uroot -p123 < /backup/all.sql #方法二: mysql> use db1; mysql> SET SQL_LOG_BIN=0; #關閉二進制日誌,只對當前session生效 mysql> source /root/db1.sql
3.事務
begin; # 開啓事務 select * from emp where id = 1 for update; # 查詢id值,for update添加行鎖; update emp set salary=10000 where id = 1; # 完成更新 commit; # 提交事務(解鎖)
注意3個關鍵點:
create table userinfo( id int primary key auto_increment, name char(12) unique not null, password char(18) not null ) insert into userinfo(name,password) values('alex','alex3714') # 用戶名和密碼到數據庫裏查詢數據 # 若是能查到數據 說明用戶名和密碼正確 # 若是查不到,說明用戶名和密碼不對 username = input('user >>>') password = input('passwd >>>') sql = "select * from userinfo where name = '%s' and password = '%s'"%(username,password) print(sql) -- :表示註釋掉--以後的sql語句 select * from userinfo where name = 'alex' ;-- and password = '792164987034'; select * from userinfo where name = 219879 or 1=1 ;-- and password = 792164987034; select * from userinfo where name = '219879' or 1=1 ;-- and password = '792164987034';
上面的輸入狀況都能查詢到結果,因此存在安全隱患,這種存在安全隱患的狀況就叫 sql注入。
爲了不 sql注入,在用pymysql時,不要再本身去拼接sql語句了,要讓mysql模塊本身去拼接。
import pymysql conn = pymysql.connect(host = '127.0.0.1',user = 'root', password = '123',database='day41') cur = conn.cursor() username = input('user >>>') password = input('passwd >>>') sql = "select * from userinfo where name = %s and password = %s" cur.execute(sql,(username,password)) # 讓mysql模塊去拼接 print(cur.fetchone()) cur.close() conn.close()