目录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