目錄python
pip3 install pymsql
mysql
方法:sql
conn = pymysql.conn():
實例化對象,創建mysql鏈接數據庫
--- host:鏈接的mysql主機ip安全
--- user:鏈接mysql的用戶app
--- password:鏈接mysql的密碼函數
--- database:鏈接mysql的數據庫工具
--- charset:鏈接mysql的字符編碼性能
cursor = conn.cursor():
創建遊標fetch
cursor.execute(sql):
執行sql語句
conn.commit():
提交,若是要增刪改的話須要提交才能執行sql
cursor.fetchall():
取出sql執行完畢的全部數據,默認以元組結果展現
cursor.fetchone():
取出sql執行完畢的一條數據
cursor.fetchmany(size):取出sql執行完畢的size條數據
conn.commit():
增刪改數據庫數據的時候要寫上這個代碼
cursor.lastrowid:
獲取最後一行記錄
cursor.close():
關閉鏈接
conn.close():
關閉鏈接
import pymysql user = input("請輸入用戶名").strip() pwd = input("請輸入密碼").strip() # 創建鏈接 conn = pymysql.connect( host="192.168.32.130", user="root", password="123", database="work", charset="utf8" ) # cursor = conn.cursor() # 執行完畢以後的結果默認以元組形式輸出 cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) # 指定輸出類型爲字典 # 定義sql語句 # sql = "insert into pymysql_test (user ,pwd) values (%s,%s)" # 增 # sql = "delete from pymysql_test where id=2;" # 刪 # sql = "update pymysql_test set pwd="123" where id=3;" # 改 sql = "select * from pymysql_test where user=%s and pwd=%s" # 查 sql = "select * from pymysql_test where user='%s' and pwd='%s'" % (user,pwd) # 查 演示sql注入,注意,佔位符會把字符串類型的引號去掉,讓它再也不是字符串類型 # sql = "select * from pymysql_test" # 查 # 執行sql語句 # cursor.execute(sql) cursor.execute(sql,(user,pwd)) # 若是要 增刪改數據的話 須要commit,查不須要 conn.commit() # 獲取最後一行的ID值 print(cursor.lastrowid) # 接收執行結果 res = cursor.fetchall() # 取出全部數據 # res = cursor.fetchone() # 取出一條數據 # res = cursor.fetchmany(2) # 取出指定條數數據,若是指定條數超過數據庫裏已有的條目則所有展現,不會報錯 print(res) # 關閉鏈接 cursor.close() conn.close() if res: print("登陸成功") else: print("登陸失敗")
那麼以上咱們對pymysql進行了簡單的使用,那麼接下來有一個安全上的問題,就是sql注入問題
之因此產生sql注入問題的緣由是 咱們沒有對用戶的數據進行約束,用戶在輸入的時候可能會隨便輸入,就會引起sql注入問題:
咱們正常登錄是這樣的:
請輸入用戶名qinyj 請輸入密碼123 sql語句是:select * from pymysql_test where user='qinyj' and pwd='123' 登錄成功
那麼有些用戶可能隨便輸入用戶名也能登錄成功,好比如下這種:
輸入用戶名:qinyj' or 1=1 #
輸入密碼:dsadsa
請輸入用戶名qinyj' # 請輸入密碼123 sql語句是: select * from pymysql_test where user='qinyj' #' and pwd='123' 登錄成功
以上用戶名輸入錯誤還能登錄成功的狀況,是由於有 #
號,mysql在碰到 這個符號以後不會執行後面的sql語句,因此至關於select * from pymysql_test
查全部的數據
這種狀況咱們就稱之爲sql注入問題,這是一個很是嚴重的問題,在公司中開發是絕對不容許的,咱們要解決這個問題能夠有兩種方法:
--- 1. 本身編寫對用戶輸入的規則,經過後才執行sql
--- 2. 使用pymysql自帶的檢驗工具 cursor.execute(sql, (user, pwd))
,將用戶名、密碼傳入執行sql的參數中。
在介紹 MySQL索引以前,咱們先建立一個表,表結構以下
mysql> desc pymysql_test; +-------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | user | varchar(32) | NO | | | | | email | varchar(32) | NO | | | | +-------+-------------+------+-----+---------+----------------+ 3 rows in set (0.00 sec)
來對這個表插入500W條數據,方便下面的講解。
import pymysql conn = pymysql.connect( host="192.168.32.130", user="root", password="123", database="work", charset="utf8" ) cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) sql = "insert into pymysql_test(user,email) values (%s,%s)" data = [] for i in range(5000000): info = ("qinyj" + str(i),"qinyj" + str(i) + "@qq.com") data.append(info) # print(data) cursor.executemany(sql,data) # 新增多條數據 conn.commit() cursor.close() conn.close() select * from pymysql_test; ... 5000000 rows in set (20.45 sec)
使用索引就是爲了提升查詢的效率,相似於新華字典中的目錄
索引的本質就是一個特殊的文件,記錄着索引信息
索引的底層原理:B + 樹
mysql> desc test; +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | id | int(11) | YES | | NULL | | | name | varchar(32) | YES | | NULL | | +-------+-------------+------+-----+---------+-------+ 2 rows in set (0.00 sec)
加速查找、不能重複、不能爲空
建立主鍵索引:primary key 一、create table test(id int auto_increment primary key)charset=utf8; 二、alter table test modify id int auto_increment primary key; 三、alter table test add primary key(id); 刪除主鍵索引: 注意:若是主鍵加上了自增的約束就不能被刪除 alter table test drop primary key;
加速查找、不能重複 unique(xxx)
惟一聯合索引:unique(xxx,xxx)
建立惟一索引:unique 一、create table test(id int auto_increment primary key,name varchar(32) not null default '',unique u_name(name))charset=utf8; 二、create unique index u_name on test(name); 三、alter table test add unique index u_name (name); 建立聯合索引: 一、create table test(id int auto_increment primary key,name varchar(32) not null default '',address varchar(32) not null default '',age int not null default 0, unique u_name_age(name,age))charset=utf8; 二、alter table pymysql_test add unique index pt_name (user,email); 刪除惟一索引: alter table test drop index u_name;
加速查找 index(xxx)
普通聯合索引:index(xxx,xxx)
建立普通索引:index 一、create table test(id int auto_increment primary key,name varchar(32) not null default '',index ix_name(name))charset=utf8; 二、create index ix_name on test(name); 三、alter table test add index ix_name (name); 建立聯合普通索引: create table test(id int auto_increment primary key,name varchar(32) not null default '',age int not null default 0,index ix_name_age (name,age))charset=utf8; 刪除普通索引 alter table test drop index ix_name;
經過觀察 *.ibd 文件可知:
因此索引不是加的越多越好
mysql> desc pymysql_test; +-------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | user | varchar(32) | NO | | | | | email | varchar(32) | NO | | | | +-------+-------------+------+-----+---------+----------------+ 3 rows in set (0.00 sec)
會下降sql的查詢效率的狀況:
在sql語句中進行四則運算
select * from pymysql_test where id*2=5127;
Empty set (6.55 sec)
使用聚合函數
select count(id) from pymysql_test;
1 row in set (4.06 sec)
查詢類型不一致的時候,若是列是字符串類型,條件也必須用引號引發來表示字符串
select * from pymysql_test where email=999;
Empty set, 65535 warnings (9.20 sec)
排序 order by
排序條件爲索引,則查詢字段必須也是索引字段,不然沒法命中
若是查詢的字段與排序字段的不是主鍵的字段,那麼速度依然很慢
select email from pymysql_test order by email desc;
若是查詢的字段與排序的字段是主鍵的字段,那麼速度仍是很快
select id from pymysql_test order by id desc;
5000004 rows in set (9.48 sec)
count(1) 或 count(列) 代替 count(*) 在mysql中沒有差異
select count(*) from pymysql_test;
select count(1) from pymysql_test;
select count(id) from pymysql_test;
1 row in set (4.29 sec)
組合索引最左前綴
何時會建立聯合索引?
根據公司業務場景,在最經常使用的幾列上添加索引
mysql> desc pymysql_test; +-------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | user | varchar(32) | NO | | | | | email | varchar(32) | NO | | | | +-------+-------------+------+-----+---------+----------------+ 3 rows in set (0.00 sec) 建立聯合索引 alter table pymysql_test add unique index pt_name (user,email); Query OK, 0 rows affected (1 min 4.77 sec) Records: 0 Duplicates: 0 Warnings: 0
建立完聯合索引以後呢,咱們使用組合查詢效率會很是高,
聯合查詢:效率很是高 select * from pymysql_test where user="qinyj1324" and email="qinyj1324@qq.com"; 1 row in set (0.00 sec) 查詢最左前前綴:效率也是很是高 select * from pymysql_test where user="qinyj122432" ; 1 row in set (0.00 sec) 查詢後面的:效率就低了 select * from pymysql_test where email="qinyj1324@qq.com"; 1 row in set (5.96 sec)
例子:
組合索引:index (a,b,c,d)
where a=2 and b=2 and c=2 and d=5 --> 命中索引
where a=2 and c=2 and d=5 -->部分命中索引
where d =5 -->沒有命中
explain關鍵字能夠模擬優化器執行sql語句,從而知道MySQL是如何處理sql語句的,分析查詢語句或是結構的性能瓶頸
咱們只須要在查詢sql語句前面加上explain就好了
explain select * from pymysql_test where email="qinyj1324@qq.com"\G;; *************************** 1. row *************************** id: 1 select_type: SIMPLE table: pymysql_test type: index possible_keys: NULL key: pt_name key_len: 196 ref: NULL rows: 4988562 Extra: Using where; Using index 1 row in set (0.00 sec)
參數解釋:
select id from pymysql_test where id=20000;
查看慢sql的相關變量
show variables like '%slow%'; +---------------------------+------------------------------------+ | Variable_name | Value | +---------------------------+------------------------------------+ | log_slow_admin_statements | OFF | | log_slow_slave_statements | OFF | | slow_launch_time | 2 | | slow_query_log | OFF | | slow_query_log_file | /data/app/mysql/localhost-slow.log | +---------------------------+------------------------------------+ show variables like '%long%'; +--------------------------------------------------------+-----------+ | Variable_name | Value | +--------------------------------------------------------+-----------+ | long_query_time | 10.000000 |
參數解釋:
配置慢查詢的變量:
set global slow_query_log = on; set global slow_query_log_file = '/data/app/mysql/myslow.log'; set global long_query_time = 1;
配置完畢以後退出重連一下就會有生成的慢查詢日誌了
ll /data/app/mysql/myslow.log -rw-rw---- 1 mysql mysql 180 Oct 31 05:37 /data/app/mysql/myslow.log