MySQL數據庫4Python操作mysql、索引、慢查詢日志


一、Python 操作 mysql

pymysql是通過python操作mysql的模塊,需要先安裝,方法:pip install pymysql

1.1python 操作 mysql

操作步驟:

1.配置連接數據庫的參數

host配置的是IP地址,若果是本機則用localhost,user配置用戶權限,之后配置賬戶和密碼,這里的賬戶密碼指登錄數據庫的賬戶和密碼,database配置需要操作的數據庫,之后是配置要鏈接的數據庫的編碼。

2.設置默認返回的數據類型

3.發送SQL指令

4.獲取返回的數據

import pymysql


#連接數據庫的參數
conn = pymysql.connect(host='localhost',user='root',
                       password='123zgh',database='test2',
                       charset='utf8')

#cursor = conn.cursor() 默認返回的是元組類型
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
#默認返回字典類型
sql = "select * from userinfo"
cursor.execute(sql)

res1 = cursor.fetchone()#取出一條數據,返回的是字典
print(res1)

res = cursor.fetchall()#取出所有的數據,返回的是列表套字典
print(res)

cursor.close()
conn.close()

{'id': 1, 'name': 'xiaozhu', 'depart_id': 1}
[{'id': 2, 'name': 'xiaoyu', 'depart_id': 1}, {'id': 3, 'name': 'laohe', 'depart_id': 2}, {'id': 4, 'name': 'longge', 'depart_id': 2}, {'id': 5, 'name': 'ludi', 'depart_id': 3}, {'id': 6, 'name': 'xiaoguo', 'depart_id': 4}]

通過例子可以看出數據的讀出是一條一條讀出的。

1.2查詢數據

Python查詢Mysql使用 fetchone() 方法獲取單條數據,使用

  • fetchall():方法獲取多條數據。
  • fetchone(): 該方法獲取下一個查詢結果集。結果集是一個對象
  • fetchall(): 接收全部的返回結果行.
  • rowcount: 這是一個只讀屬性,並返回執行execute()方法后影響的行數。
import pymysql


#連接數據庫的參數
conn = pymysql.connect(host='localhost',user='root',
                       password='123zgh',database='test2',
                       charset='utf8')

#cursor = conn.cursor() 默認返回的是元組類型
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
#默認返回字典類型
sql = "select * from userinfo"
cursor.execute(sql)

res1 = cursor.fetchone()#取出一條數據,返回的是字典
print(res1)

res = cursor.fetchall()#取出所有的數據,返回的是列表套字典
print(res)

res2 = cursor.rowcount#返回的是int型,不能加括號
print(res2)

conn.commit()#對數據的增刪改一定要提交,否則更改不成功,而且主鍵id還會增加,pycharm還不會報錯,很坑
cursor.close()
conn.close()

1.3增加(添加、更新)數據

使用到的方法:

cursor.execute()增加一條數據

cursor.executemany()增加多條數據

conn.commit()提交發送的SQL語句

對數據的增刪改一定要提交,否則更改不成功,而且主鍵id還會增加,pycharm還不會報錯,很坑

print(cursor.lastrowid)獲取最后一行的ID值,只是將原來的最后一行id加一,如果一次插入多行,並不能正確顯示主鍵最后一行的id

例子1插入一條數據

import pymysql


#連接數據庫的參數
conn = pymysql.connect(host='localhost',user='root',
                       password='123zgh',database='test2',
                       charset='utf8')

#cursor = conn.cursor() 默認返回的是元組類型
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
#默認返回字典類型
sql = "insert into user (name,password) values (%s,%s)"
cursor.execute(sql,('abc','deg'))#括號內填寫需要增加的數據,此方式為增加一條數據
print(cursor.lastrowid)#獲取最后一行的ID值
conn.commit()#對數據的增刪改一定要提交,否則更改不成功,而且主鍵id還會增加,pycharm還不會報錯,很坑
cursor.close()
conn.close()
mysql> select * from user;
+----+----------+----------+
| id | name     | password |
+----+----------+----------+
|  2 | xiaoming | 1563sdi  |
|  3 | abc      | deg      |
|  5 | abc      | deg      |
+----+----------+----------+
3 rows in set (0.00 sec)

例子二插入多條數據

import pymysql

#連接數據庫的參數
conn = pymysql.connect(host='localhost',user='root',
                       password='123zgh',database='test2',
                       charset='utf8')

#cursor = conn.cursor() 默認返回的是元組類型
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
#默認返回字典類型
data = [('xiaozhu1','145656'),('xiaohzhu2','14965'),('xiaozhu3','61500')]
sql = "insert into user (name,password) values (%s,%s)"
# cursor.execute(sql,('abc','deg'))#括號內填寫需要增加的數據


cursor.executemany(sql,data)
print(cursor.lastrowid)#獲取最后一行的ID值,只是將原來的最后一行id加一,
# 如果一次插入多行,並不能正確顯示主鍵最后一行的id
conn.commit()#對數據的增刪改一定要提交,否則更改不成功,而且主鍵id還會增加,pycharm還不會報錯,很坑
cursor.close()
conn.close()

1.4修改數據

修改數據、增加數據、刪除數據其實就是將相應的SQL語句和要修改的對象發送給數據庫,然后數據庫按照相應的語句進行執行。

import pymysql

conn = pymysql.connect(host='localhost',user='root',
                       password='123zgh',database='test2',
                       charset='utf8')
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)

sql = "update user set name=%s where id=%s"

cursor.execute(sql,('xiaoyu',2))
conn.commit()
cursor.close()
conn.close()

1.5刪除數據

sql = "delete from user where id=%s"

import pymysql

conn = pymysql.connect(host='localhost',user='root',
                       password='123zgh',database='test2',
                       charset='utf8')
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)

#sql = "update user set name=%s where id=%s"
sql = "delete from user where id=%s"

cursor.execute(sql,(1,))#這里的數據元組里面只有一個元素時不加逗號也可以正常刪除,但是最好加上
conn.commit()
cursor.close()
conn.close()

1.6SQL注入問題

1.6.1問題的引入

當我們的登錄程序這樣寫的時候,我們輸入用戶名:xxx ' or 1=1 #就可以將發送到mysql的指令改變以至於不用用戶名和密碼也能夠獲取用戶的數據,如輸入以后成了select * from user where name='xiaozhu' or 1=1 #' and password='156'則后面的密碼部分被注釋,where條件也發生了改變or后面的條件始終成立。

import pymysql

user = input('輸入用戶名:').strip()
pwd = input('輸入密碼:').strip()

conn = pymysql.connect(host='localhost',user='root',password='123zgh',
                       database='test2',
                       charset='utf8')
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)

sql = "select * from user where name='%s' and password='%s'" % (user,pwd)
print(sql)

cursor.execute(sql)
# print(sql)
res = cursor.fetchall()
print(res)
cursor.close()
conn.close()
if res:
    print('登錄成功')

else:
    print('登錄失敗')

1.6.2解決方法

我們在寫登錄程序時可以使用pymysql提供的方法,或者自己寫程序判斷用戶輸入的字符是否有問題。

sql = "select * from user where name=%s and password=%s"

cursor.execute(sql,(user,pwd))

import pymysql

user = input('輸入用戶名:').strip()
pwd = input('輸入密碼:').strip()

conn = pymysql.connect(host='localhost',user='root',password='123zgh',
                       database='test2',
                       charset='utf8')
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)

sql = "select * from user where name=%s and password=%s" 

cursor.execute(sql,(user,pwd))
# print(sql)
res = cursor.fetchall()
print(res)
cursor.close()
conn.close()
if res:
    print('登錄成功')

else:
    print('登錄失敗')

二、索引

mysql的索引作用和字典的索引,圖書館的圖書索引的作用都是一樣的,目的都是為了提高查找的速度。

2.1索引的本質

數據庫的索引本質是一個特殊的文件,可以提高數據的查找速度。

2.2索引的底層原理

底層原理是B+樹(涉及的數據結構與算法知識較多,以后有機會再做介紹)

2.3索引的分類

2.3.1主鍵索引

依據primary key進行查找數據,特點:提高查找效率,且主鍵的記錄數據不重復,不為空

2.3.2唯一索引

添加方式:某一列的字段名的數據類型后面加unique(字段名)

特點:提高查找效率,且唯一索引記錄數據不重復,不為空

2.3.3聯合唯一索引

添加方式:unique(字段名1,字段名2......)

特點:提高查找效率,且組合在一起的字段記錄數據不重復(單列數據可以重復,組合在一起不能重復),不為空

2.3.4普通索引

index(字段名)

特點:沒有上述主鍵唯一索引對數據的要求

2.3.5聯合索引

index(字段1,字段2……)

特點:沒有上述主鍵唯一索引對數據的要求

2.4索引的創建

2.4.1主鍵索引的創建與刪除

2.4.1.1新增主鍵索引

方式1
create table xxx(
id int auto_increment primary key
);
方式2
create table xxx(
id int auto_increment, primary key(id)
);
方式3
alter table xxx change id id int auto_increment primary key;
方式4
alter table yyy add primary key (id);

2.4.1.2刪除主鍵索引

如果主鍵是自增id,不能直接使用下面的方法刪除,需要先將其修改為非自增id,然后再用下面的方法刪除(這種情況在實際應用中幾乎不會出現)。

alter table yyy drop primary key;

2.4.2唯一索引的創建與刪除

2.4.2.1創建唯一索引

方式1
create table XXX(
    id int auto_increment primary key,
	name varchar(32) not null default '',
	unique u_name (name) )
    #u_name是給唯一索引起的名字,方便以后刪除索引或查找問題
方式2
create unique index 索引名 on 表名 (字段名);
方式3
alter table 表名 add unique index 索引名(字段名)

2.4.2.2刪除唯一索引

alter table 表名 drop index 索引名;

2.4.3普通索引的創建與刪除

2.4.3.1普通索引的創建

方式1
create table 表名(
    id int auto_increment primary key,
    name varchar(32) not null default '',
    index 普通索引名(字段名)
)
方式2
create index 索引名 on 表名(字段名);
方式3
alter table 表名 add index 索引名(字段名);

2.4.3.2普通索引的刪除

alter table 表名 drop index 索引名;

2.5索引的優缺點

優點:加快了查詢速度

缺點:占用了大量的磁盤空間*.ibd是存儲數據和索引的文件,可通過查看這個文件的大小對比創建索引前和創建索引后的差別。

2.6不會命中索引的情況

2.6.1不會命中索引的情況

不會命中索引指:創建的索引么有用上,沒有達到快速查找的目的。

情況1

在SQL語句中使用四則運算,會降低SQL的查詢效率。

情況2

在SQL語句中使用函數。如

select * from user where reverse(email) = 'guanghao';
#reverse的功能是反轉'guanghao'然后在email里面查找

情況3

類型不一致:如果列是字符串類型,傳入的條件必須先加引號,不然找不着。

情況4

排序條件為索引,則select字段也必須是索引字段,否則無法命中。

如使用order by時

select name from user order by email desc;

上面的SQL語句如果email是索引,則select email可以通過索引快速查找,如果select 的不是索引那一列,則不會觸發索引,查找速度依然很慢。

例外情況:如果對主鍵排序,查找其他列條件,速度也很快。

如select * from 表名 order by id desc;

情況5

count(1)、count(列)、count(*)查找速度沒太大差別

情況6

組合索引遵循最左前綴原則

當創建聯合索引時如name,email均創建了索引,則可以命中索引的查找方式有:

方式1
select * from user where name='guanghao' and email='guanghao@qq.com';
方式2
select * from user where name='guanghao';

如果where 后面的條件是email則無法命中索引。

如果聯合索引的列不止兩列則要從左向右按順序排列查找才可以命中索引,如果中間跳過了某列只要最左邊列存在就能夠命中索引。如下例

index(a,b,c,d)
where a=1 and b=2 and c=3 and d=4 #命中索引
where a=1 and c=3 and d=4 #命中索引

2.6.2查看索引是否命中的方法

explain select * from 表名 where 查詢的條件\G;

如:
mysql> explain select password from user where id=6\G;
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: user
         type: const
possible_keys: PRIMARY 可能用到的索引
          key: PRIMARY 確實用到的索引
      key_len: 4       索引長度
          ref: const   
         rows: 1       掃描的長度(這里可以確定是否使用了索引)
        Extra: NULL    是否使用了索引
1 row in set (0.00 sec)

2.6.3索引覆蓋

索引覆蓋就是按照索引去查數據。

2.7慢查詢日志

2.7.1查看慢SQL的相關變量

mysql> 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       | E:\mysql\mysql-5.6.46-winx64\data\ZGH-PC-slow.log |記錄慢日志的位置,
+---------------------------+---------------------------------------------------+可配置
5 rows in set (0.03 sec)

mysql> show variables like '%long%';
+--------------------------------------------------------+-----------+
| Variable_name                                          | Value     |
+--------------------------------------------------------+-----------+
| long_query_time                                        | 10.000000 |
默認當查找時間大於10秒會記錄為慢SQL,我們需要對其進行配置修改其記錄為慢SQL的時間。

2.7.2配置慢SQL的變量

set global 變量名 = 值
				 
set global slow_query_log = on;慢日志查詢配置為on
				
set global slow_query_log_file="D:/mysql-5.6.46/data/myslow.log";配置慢日志存儲路徑(路徑不能有空格,否則會配置不成功)
				
set global long_query_time=1;配置記錄為慢日志的捕捉時間


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM