1. Mysql 数据库 V3.1
官方文档: https://dev.mysql.com/doc/refman/5.7/en/binary-installation.html
1-1 数据库的基本使用
-
数据库介绍:关系型数据库
- 列 — 字段
- 行 — 记录
- 唯一标记某个字段 — 主键
-
RDBMS、MySQL介绍
-
MySQL服务器、客户端安装以及使用
sudo apt-get install mysql-server
sudo service mysql start
ps ajx|grep mysql / ps -aux|grep "mysql"
sudo service mysql stop
sudo service mysql restart
-
通过navicat操作数据库
数据库的编码设置成什么,在数据库中创建数据表默认的是数据库的编码
-
数据类型、约束
- 数据完整性
- 一个数据库就是一个完整的业务但愿,可以包含多张表,数据存储在表中
- 在表中为了更准确的获取数据,保证数据的正确有效,可以在创建表的时候,为表添加一些强制的验证,包括字段的类型和约束
- 数据类型:够用就行,尽量使用取值范围小的,而不用大的,这样可以更多的节省空间
- 整数 : int
- 小数 : decimal
- 字符串 : varchar/char
- 日期时间 : date,time,datetime
- 枚举类型(enum)
- 特别说明的类型如下:
- decimal 表示浮点数,如 decimal(5,2)表示共存5位数,小数占2位
- char表示固定长度的字符串,如char(3),如果填充'ab'时会补一个空格为'ab '
- varchar表示可变长度的字符串,如varchar(3),如果填充'ab'时会存储'ab'
- 字符串 text 表示存储大文本,当字符大于4000时推荐使用
- 对于图片、音频、视频等文件,不存储在数据库中,而是上传到某个服务器上,然后在表中存储这个文件的路径
- 约束
- 主键 primary key : 物理上存储的顺序
- 非空 not null: 此字段不允许填写空值
- 唯一 unique:此字段的值不允许重复
- 默认 default:当不填写此值时会使用默认值,如果填写时以填写为准
- 外键 foregin key:对关系字段进行约束,当为关系字段填写值时,会到关联的表中查询此值是否存在,如果存在则填写成功,如果不存在则填写失败并抛出异常
- 说明:虽然外键约束可以保证数据的有效性,但是在进行数据的crud(增🏠、修改、删除、查询)时,都会降低数据库的性能,所以不推荐使用,那么数据的有效性如何保证?答:可以在逻辑层近行控制
数值类型(常用)
类型 | 字节大小 | 有符号范围(Signed) | 无符号范围(UnSigned) |
---|
字符串
int最大为2145483647,手机号码应该用bigint 1bit位 1字节=8bit 1k=1024字节 1兆=1024K 1G=1024M 1T=1024G -
(重点)-数据库的操作
- 注释 :
-- 注释 - 链接数据库:mysql -uroot -p
- 退出:ctrl+d / quit / exit
- 查看所有数据库:show databases;
- 显示当前数据库时间:select now();
- 显示当前数据库版本:select version();
- 数据库操作:
- show databases;
- create database dbname [charset=utf8];
- show create database dbname;
- drop database
dbname ; - use dbname;
-
(重点)-数据表的操作
- 数据表
- desc table_name;
- show tables;
- create table student(
id int unsigned not null auto_increment primary key, name varchar(30), age tinyint unsigned default 0, high decimal(5,2), gender enum(“男”,“女”,“中性”,“保密”), cls_id int unsigned )engine=InnoDB auto_increment=2 default charset=utf8;
- auto_increment 自增
- nut null
- primary key 主键
- default 默认值
- create table 表名(字段名 类型 约束[,字段名 类型 约束])
- show create table 表名字;
- 修改表
- 添加字段:alter table 表名 add 列名 类型;
- 修改字段:alter table 表名 change 原列名 新列名 类型 默认值;
- 删除字段:alter table 表名 drop 列名;
-
(重重点)-数据的增删改查 curd
- 插入数据:insert into 数据表 values()[,()];
insert into student values
- (0,“小红”,20,“男”,1,“1990-10-01”),
- (null,“小红1”,20,“男”,1,“1990-10-01”),
- (default,“小红”,20,“男”,1,“1990-10-01”);
枚举中的下标从 1 开始 - (0,“小红”,20,“1”,1,“1990-10-01”),
- (null,“小红1”,20,“2”,1,“1990-10-01”),
- (default,“小红”,20,“3”,1,“1990-10-01”);
- 部分插入
insert into students(name,gender)value(“大桥”,4); - 修改数据:update table_name set 列=value1[,列=value,列=value where 条件];
- 查询:select * from table where xxx;
- 删除(不轻易使用):delete from table where xxx;
truncate table table_name; alter table add is_delete bit default 0; -
物理删除和逻辑删除
1-2 数据库查询
mysql> -- 创建一个数据库
mysql> create database python_test charset=utf8;
Query OK, 1 row affected (0.00 sec)
mysql> -- 使用数据库
mysql> use python_test;
Database changed
mysql> select database();
+-------------+
| database() |
+-------------+
| python_test |
+-------------+
1 row in set (0.00 sec)
mysql> -- 创建一个数据表
mysql> -- students
mysql> create table students(
id int unsigned auto_increment primary key not null,
name varchar(30),
age tinyint unsigned default 0,
heigh decimal(5,2),
gender enum("男","女","中性","保密") default "保密",
cls_id int unsigned default 0,
is_delete bit default 0
);
mysql> -- classes
mysql> create table classes(
id int unsigned auto_increment primary key not null,
name varchar(30) not null
);
mysql> -- 向students表中插入数据
insert into students values
(0,"小明",18,180.00,2,1,0),
(0,"小明2",18,185.00,2,2,0),
(0,"小明3",29,175.00,1,1,0),
(0,"小明4",29,160.00,2,1,0),
(0,"小明5",59,150.00,4,2,1),
(0,"小明6",38,172.00,2,1,0),
(0,"小明7",28,null,2,1,0),
(0,"小明8",18,181.00,1,1,0),
(0,"小明9",36,166.00,1,2,0),
(0,"小明10",27,162.00,2,2,0),
(0,"小明11",25,180.00,3,3,0),
(0,"小明12",33,170.00,1,4,0),
(0,"小明13",34,176.00,2,5,0);
mysql>-- 向class中插入数据
insert into classes values(0,"python_01期"),(0,"python_02期"),(0,"python_04期");
- 基本的查询
select * from students; select * from classes; select id, name from classes; select name,age from students; select name as “姓名”,age as “年龄” from students; select distinct gender from students; - 条件查询
- =/>/</!=[<>]
- and/or/not
- like[%/_]/rlike 正则
- 范围查询、null
- 非连续的范围:in/not…in…
- 连续的范围,包含两边的值:between…and…/not between…and…
- 判断空:is null
- 排序:默认按照主键排序
- order by 支持多字段排序;第一个排完后,按照第二个字段,
- 聚合、分组
- 聚合函数:count/max/min/avg/sum/round/ group_concat()
- 分组和聚合一起使用:group by
mysql> select gender,group_concat(name,"_",age," ","id") from students group by gender;
+--------+----------------------------------------------------------------------------------------------------+
| gender | group_concat(name,"_",age,"_","id") |
+--------+----------------------------------------------------------------------------------------------------+
| 男 | 小明3_29_id,小明8_18_id,小明9_36_id,小明12_33_id |
| 女 | 小明_18_id,小明2_18_id,小明4_29_id,小明6_38_id,小明7_28_id,小明10_27_id,小明13_34_id |
| 中性 | 小明11_25_id |
| 保密 | 小明5_59_id |
+--------+----------------------------------------------------------------------------------------------------+
mysql> select gender,group_concat(name,"_",age,"_","id"),avg(age) from students group by gender having avg(age)>30;
+--------+-------------------------------------+
| gender | group_concat(name,"_",age,"_","id") |
+--------+-------------------------------------+
| 保密 | 小明5_59_id |
+--------+-------------------------------------+
where 对原表的判断;having 对查询结果的筛查;
- 分页:page 页码,num 每页的个数
- limit start,end;[(page-1)*num,num]
- 链接查询
- 内链接(交集): inner join … on …
- 左连接(外链): left join … on …
- 右连接(外链): right join … on … having …
mysql> select s.*,c.name from students as s left join classes as c on s.cls_id = c.id having c.name is null;
+----+----------+------+--------+--------+--------+-----------+------+
| id | name | age | heigh | gender | cls_id | is_delete | name |
+----+----------+------+--------+--------+--------+-----------+------+
| 12 | 小明12 | 33 | 170.00 | 男 | 4 | | NULL |
| 13 | 小明13 | 34 | 176.00 | 女 | 5 | | NULL |
+----+----------+------+--------+--------+--------+-----------+------+
2 rows in set (0.01 sec)
- 自关联
- 案例:[一张表解决关联] 省、市、县、乡| 公司部门 |id-name-parent_id
- 一个表中的一个字段关联另外一个字段
- select province.atitle,city.atitle from areas as province inner join areas as city on city.pid=province.aid having province.atitle=“山东省”;
- 子查询-简单[少用比较浪费时间]
select * from students where height=(select max(height) from students); - 数据库设计
- 数据库设计软件:power designer , db designer
- 范式 NF
- 1NF: 每个字段不可拆分
- 2NF: 必须有主键,主键可以有多个字段组成;其余字段全部依赖主键;
- 3NF:
- E-R 模型
- E表示entry,实体
- R表示relationship,关系
- 多对一:在多添加字段
- 多对多:新加中间表
1-3 Mysql与Python交互
- mysql-client 客户端的快捷键
行首:ctrl+a; 行尾:ctrl+e - update 里面用两个表关联
旧: goods:id|name|cate_name|brand_name|is_show|is_saleoff
goods_cates:id|name
goods_brands:id|name
--- goods_cates ---
create table goods_cates(
id int unsigned primary key auto_increment,
name varchar(40) not null
);
-- 数据插入
insert into goods_cates(name) select cate_name as name from goods group by cate_name;
-- 拆分表并赋值
update goods as g inner join goods_cates as c on g.cate_name = c.name set g.cate_name = c.id;
-- 修改表字段和类型
alter table goods change cate_name cate_id int unsigned not null;
-- 关联外键:确定相对应列的对比
alter table goods add foreign key(cate_id) reference goods_cates(`id`);
--- goods_brands ---
-- 注意:在创建表的时候一起插入数据
需要对brand_name用as起别名,否则name字段就没有值
create table goods_brands(
id int unsigned primary key auto_increment,
name varchar(40) not null select brand_name as name from goods group by brand_name
);
--- goods ---
alter table goods
change cate_name cate_id int unsigned not null,
change brand_name brand_id int unsigned not null;
alter table goods
add foreign key(cate_id) reference goods_cates(`id`),
add foreign key(brand_id) reference goods_brands(`id`),
alter table goods drop foregin key 外键名称;
`在实际开发中很少用到外键,因为效率比较低`
- python安装pymsql
- python2.x MySQLdb
- python3.x pymysql
- 安装
- pip -V
- 有网: pip3 install pymysql
- 无网:pip3 install “本地路径”
- python操作sql:查询数据
- 流程
开始--创建connection--获取cursor---[执行查询|执行操作]--关闭cursor--关闭connection--结束 from pymysql import *
def main():
conn = connect(host='127.0.0.1',port=3306,user='root',password='123456',database='python_test',charset='utf8')
cursor = conn.cursor()
cursor.execute("select * from goods;")
cursor.fetchone()
cursor.fetchmany()
cursor.close()
conn.close()
if __name__ == "__main__":
main()
- 案例:京东商城-查询|添加|删除|修改数据
注意:添加|删除|修改数据 必须提交 conn.commit() | conn.rollback()
from pymysql import connect
class JD():
def __init__(self):
self.conn = connect(host='127.0.0.1',port=3306,user='root',password='123456',database='python_test',charset='utf8')
self.cursor = self.conn.cursor()
def __del__(self):
self.cursor.close()
self.conn.close()
def excute_sql(self, sql):
def show_all_items(self):
def show_cates(self):
def show_brands(self):
def add_brands(self):
def get_info_by_name(self):
@staticmethod
def print_num()
print("----京东----")
print("所有商品")
print("所有商品分类")
print("所有商品分类品牌")
return input("请输入功能对应的序号:")
def run():
while True:
num = self.print_num()
if num == "1":
self.show_all_items()
elif num == "2":
self.show_cates()
elif num == "3":
self.show_brands()
elif num == "4":
self.add_brands()
elif num == "5":
self.get_info_by_name()
else:
print("输入有误,重新输入")
def main():
jd = JD()
jd.run()
if __name__ == "__main__":
main()
- 添加:防止SQL注入
1-4 Mysql高级
- 视图 view:虚拟的表
- 提高了重用性,就像一个函数
- 对数据库重构,却不影响程序的运行
- 提高了安全性能,可以对不同用户
- 让数据更清晰
- 事务
start transaction; // -- begin
select balance from checking where customer_id = 10233276;
update checking set balance = balance - 200.00 where customer_id = 10233276;
update saving set balance = balance + 200.00 where customer_id = 10233276;
commit;
- 四大特性:(简称ACID)
- 原子性(Atomicity)
- 一致性(Consistency)
- 隔离性(isolation)
- 持久性(durability)
- 索引
注意:建立太多索引将会影响插入和更新的速度,因为它同样需要更新每个索引文件
- 当数据量很大,查询数据会变得很慢?优化方案:索引
- 是什么? 索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),他们包含着对数据表里所有记录的引用指针*;更通俗的说,数据库索引好比是一本书前面的目录,能加快数据库的查询速度
- 目的:提高查询效率
- 原理:树 B-Tree
-- 开启时间监测
set profiling = 1;
-- 查看执行时间
show profiles;
-- 索引操作:当数据库创建了,主键和外键时候会相应创建索引
show index from table_name;
create index index_name on table_name(colum_name(长度));
drop index index_name on table_name;
- (了解)账户管理
- 在生产环境下操作数据库时绝对不可以使用root账户连接,而是创建特定的账户,授予这个账户特定的操作权限,然后连接进行操作,主要的操做就是数据的crud
- MySQl账户体系:根据账户具有的权限的不同,MySQl的账户可以分为以下几种
- 服务实例级账号:启动一个mysqld,即为一个数据库实例;如果某用户如root,拥有服务实例级别分配的权限,那么该账号就可以删除所有的数据库,连同数据库中的表
- 数据库级别账号:对特定数据库进行增删改查的所有操作
- 数据表级别账号:对特定表执行增删改查所有操作
- 字段级别的权限:对某些表的特定字段进行操作
- 存储程序级别的账号:对存储程序进行增删改查的操作
- 账户的操作主要包括创建账户、删除账户、修改密码、授权权限等
注意:1.进行账户操作时,需要使用root账户登陆,这个账户拥有最高的实例级权限 2.通常都是用数据库级操作权限
-- 创建账户授权
all privileges
grant 授权列表 on 数据库 to `用户名`@`访问主机` identified by '密码';
show grants for `用户名`@`访问主机`;
grant select on jing_dong.* to 'laowang'@'localhost' identified by '123456';
show grants for laowang@localhost;
-- 修改
grant 授权列表 on 数据库 to `用户名`@`访问主机` with grant option;
flush privileges;
-- 修改用户密码
update user set authentication_string=password('新密码') where user='用户名';
flush privileges;
-- 删除用户
drop user `用户名`@`访问主机`;
flush privileges;
- Mysql 主从
- 功能
- 主从同步的机制
- 配置主从同步的基本步骤
- 在主服务器上,必须开启二进制日志机制和配置一个独立的ID
- 在每一个从服务器上,配置一个唯一的ID,创建一个用来专门复制主服务器数据的账号
- 在开始复制进程前,在主服务器上记录二进制文件的位置信息
- 如果在开始复制之前,数据库中已经有数据,就必须先创建一个数据库快照(可以使用mysqldump导出数据库,或者直接复制数据文件)
- 配置从服务器要链接的主服务器的IP地址和登陆授权,二进制日志文件名和位置
- 详细配置主从同步的方法
- 步骤一:备份
mysqldump -u用户名 -p密码 数据库名称>xxx.sql - 步骤二:恢复
注意:链接数据库,需要手动创建新的数据库 mysql -u用户名 -p密码 数据库名<xxx.sql source xxx.sql
- 步骤三:配置主服务器 master
sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf
server-id = 1
log_bin = /var/log/mysql/mysql-bin.log
sudo service mysql restart
- 步骤四:配置从服务器 salve
sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf
server-id = 2
sudo service mysql restart
- 步骤五:在master创建一个 用于从服务器同步数据使用的账号
mysql -uroot -p
grant replication slave on *.* to `slave`@`%` identified by 'slave';
flush privileges;
show master status; // 赋值到 master_log_file
- 步骤六:
change master to master_host='',master_user='slave',master_password='slave',master_log_file='',master_log_pos=590;
start slave; # 开启同步状态
show slave status; # 查看同步状态
********************** row ******************
Slave_IO_Running:Yes
Slave_SQL_Running:Yes
2. redis 数据库
https://github.com/redis/redis 官方文档 https://www.redis.net.cn/tutorial/3505.html
3. MongoDB数据库
官方文档 https://www.mongodb.com/docs/manual/indexes/
介绍
优势: 易扩展;大数据量高性能;灵活的数据模型,高可用 缺点: 数据可能回重复,占用更多的资源
存储的数据类型: Object ID: 文档ID|保证每个文档的唯一性 (12字节的16进制数 前4字节:当前时间戳; 接下来3字节:机器ID; 接下来2字节:mongodb进程id 最后3字节:简单的增量值) String:字符串,常用,必须是有效的UTF-8 Boolean:存储一个布尔值,true或者false Integer Double Arrays Object Null Timestamp Date: new Date(‘2018-01-05’)
安装和启动
安装(-y 默认是yes)
sudo apt-get install -y mongodb-org
其他的安装方式
1.下载压缩包
2.解压缩
tar -zxvf mongodb-linux-x86_64-*****.tgz
3.移动到 /usr/local 目录下
sudo mv -r mongodb-linux-x86_64-*****/ /usr/local/mongodb
4.将可执行文件添加到path
export PATH=$PATH:/usr/local/mongodb/bin
查看帮助
mongod --help
启动[多方式]
sudo mongod --config /usr/local/mongodb/mongod.conf
启动
sudo service mongod start
停止
sudo service mongod stop
重启
sudo service mongod restart
查看时候启动成功
ps ajx|grep mongod
配置文件位置
/etc/mongod.conf
默认端口
27017
日志位置
/var/log/mongodb/mongod.log
客户端 mongo
启动本地客户端: mongo 查看帮助: mongo --help 退出: exit 或 ctrl+c
it 翻页
增删改查
注意:数据库 use 时候,自动创建数据库。
查看数据库列表 show dbs/show database;
选择数据库 use dbname;
查看当前数据库 db;
删除数据库 db.dropDatabase()
数据存储在集合里面
不手动创建集合:向不存在集合中第一次加入数据时,集合会被创建出来
手动创建集合
db.createCollection(name,options)
db.createCollection("stu")
db.createCollection("sub",{capped:true,size:10})
参数capped默认值是False表示不设置上限,值true表示设置上限
参数size:当capped值为true时,需要指定此参数,表示上线大小,当文档达到上限时,会将之前的数据覆盖,单位为字节
查看集合
show collections
删除集合
db.集合名称.drop()
插入
db.集合名称.insert(document) # _id 存在就会报错!!!
db.集合名称.save(document) # 文档_id存在修改,不存在_id添加
查找 db.集合名称.find() 更新 db.集合名称.update(,,{multi:}) db.集合名称.update({name:“xiaowang”},{$set:{name:“xiaozhang”}}) 删除 db.集合名称.remove(,{justOne:true}) justOne:只删除一条的效果
高级查询
- find() 查询
db.集合名称.find({条件文档}) - findOne() 查询一条
db.集合名称.findOne({条件文档}) - pretty() 将结果格式化
db.集合名称.find({条件文档}).pretty() - skip limit
db.集合名称.find().limit(4).skip(5) db.集合名称.find().skip(5).limit(4) - KaTeX parse error: Expected '}', got 'EOF' at end of input: … db.集合名称.find({where:function(){
return this.age>30;} }) - 投影:选择返回结果的字段
db.集合名称.find({},{字段名:1,字段名称:0,…}) # 1字段name返回,0不反回,默认不返回 默认:对于_id列默认是显示的,如果不显示需要明确设置为0 其他字段不显示默认不写 - 排序
db.集合名称.find({}).sort({字段名称:[1|-1]}) 降序 -1;升序:1 - 统计个数
db.集合名称.find({条件}).count() db.集合名称.count({条件}) - 消除重复
db.集合名称.distinct(‘去重字段’,{条件})
关系运算:大小比较("$cmp")、等于("$eq")、大于("$gt")、大于等于("$gte")、小于("$le")、小于等于("$lte")、不等于("$ne")、判断 null ("$ifNull"),这些返回值都是 boolean 值类型的。
逻辑运算:与("$and")、或("$or")、非 ("$not")
字符串操作:连接("$concat")、截取("$substr")、转小写("$toLower")
范围内 $in
或者 $or
and: 添加多个字段
db.集合名称.find({age:{$gt:23}})
备份恢复
- 备份
mongodump -h dbhost -d dbname -o dbdirectory -h 服务器地址,也可以指定端口号 -d 需要备份的数据库名称 -o 备份的数据库存放位置,此目录中放着备份出来的数据 - 恢复
mongorestore -h dbhost -d dbname --dir dbdirectory –dir 备份数据所在的位置
聚合命令 aggregate
聚合是基于数据处理的聚合管道,每一个文档通过一个由多个阶段(stage)组成的管道, 可以对每个阶段的管道进行分组、过滤等功能,然后经过一系列的处理、输出相应的结果 db.集合名称.aggregate({管道:{表达式}})
# 常用管道
$group:将集合中的文档分组,可用于统计结果
$match:过滤数据,只输出符合条件的文档
$project:修改输入文档的结构,如重命名、增加、删除字段、创建计算结果
$sort:将输入文档排序后输出
$limit:限制聚合管道返回的文档数
$skip:跳过指定数量的文档,并返回余下的文档
$unwind:将数组类型的字段进行拆分
#表达式
语法:表达式:'$列名'
$sum:计算总和,$sum:1 表示以一倍计数
$avg:计算平均值
$min:获取最小值
$max:获取最大值
$push:在结果文档中插入值到一个数组中
$first:根据资源文档的排序获取第一个文档数据
$last:根据资源文档的排序获取最后一个文档数据
$group
g
r
o
u
p
对应字典中有几个键,结果中就有几个键分组依据需要放
到
i
d
里面取不同的字段的值需要使用
,
′
g
e
n
d
e
r
,
group 对应字典中有几个键,结果中就有几个键 分组依据需要放到 _id 里面 取不同的字段的值需要使用,'gender,
group对应字典中有几个键,结果中就有几个键分组依据需要放到i?d里面取不同的字段的值需要使用,′gender,age’ 取字典嵌套字典中的值的时候$_id.字段 能够按照多个键进行分组 {$group:{_id:{country:'$country',province:'$province'}}} 结果是 {_id:{country:"",province:""}}
- _id表示分组的依据,使用某个字段的格式为’KaTeX parse error: Expected '}', got 'EOF' at end of input: …合名称.aggregate({group:{
_id:'KaTeX parse error: Expected '}', got 'EOF' at end of input: …ender', count:{sum:1}, awg_age:{
a
v
g
:
"
avg:"
avg:"age"} }}) - Group by null
db.集合名称.aggregate({KaTeX parse error: Expected '}', got 'EOF' at end of input: …d:null, count:{sum:1}, awgAge:{
a
v
g
:
"
avg:"
avg:"age"} }})
多字段同时分组
高级语法
sort skip limit
先写 skip 再 limit,效率高一些
unwind
数据 t2 {“username”:“Alex”,“tag”:[‘C#’,‘Java’,‘C++’]} 如何获取tag的长度? db.t2.aggregate({KaTeX parse error: Expected 'EOF', got '}' at position 24: …sername:'Alex'}}?,{unwind:‘$tags’}) 结果: {“username”:“Alex”,“tag”:“C#”} {“username”:“Alex”,“tag”:“Java”} {“username”:“Alex”,“tag”:“C++”}
注意: db.t3 {“username”:“Alex”,“tag”:[‘C#’,‘Java’,‘C++’]} {“username”:“Bom”,“tag”:[]} {“username”:“Jone”,“tag”:[‘C#’]}
db.inventory.aggregate({ {KaTeX parse error: Expected '}', got 'EOF' at end of input: …nd:{ path:'字段名称’, preserveNullAndEmptyArrays: #防止丢失数据 }})
索引建立
索引:提升查询速度 分类: 单键索引 多键索引
mongoshell是js的交互环境
测试:插入10万条数据
for(i=0;i<100000;i++;){db.t255.insert({name:'test'+i,age:i})}
db.t1.find({name:'test10000'})
db.t1.find({name:'test10000'}).explain('executionStats')
建立索引之后对比
语法:db.集合.ensureIndex({属性:1}) 1表示升序,-1 降序
具体操作:db.t1.ensureIndex({name:1})
db.t1.find({name:'test10000'}).explain('executionStats')
-
查看 db.collection.getIndexes() 该语法命令运行要求是MongoDB 3.0+ -
创建 语法:db.collection.createIndex(keys, options) db.collection.ensureIndex({“name”:1},{“unique”:true}) -
删除 说明:可以移除指定的索引,或移除所有索引 db.comment.dropIndex({userid:1}) 所有索引的移除 db.collection.dropIndexes() -
分析查询性能 分析查询性能(Analyze Query Performance)通常使用执行计划(解释计划、Explain Plan)来查看查询的情况,如查询耗费的时间、是 否基于索引查询等。 那么,通常,我们想知道,建立的索引是否有效,效果如何,都需要通过执行计划查看。 语法:db.collection.find(query,options).explain(options) db.comment.find({userid:“1003”}).explain() 关键点看: “stage” : “COLLSCAN”, 表示全集合扫描 关键点看: “stage” : “IXSCAN” ,基于索引的扫描
mongodb mysql redis 的区别和使用场景
- mysql是关系数据库,支持事务
- mongodb,redis是非关系数据库,不支持事务
- mysql、redis、mongodb 的使用根据如何方便进行选择
- 希望速度快的时候,用mongodb和redis
- 数据量过大的时候,频繁使用的数据存入redis、其他的存入mongodb
- mongodb不用提前建表建数据库,使用方便,字段数量不确定的时候使用mongodb
- 后续需要用到数据关系的时候,此时考虑mysql
爬虫数据去重,实现增量式爬虫
- 使用数据库建立关键字段的唯一索引进行去重
- url地址去重
- 使用场景
- url地址对应的数据不会变的情况,url地址能够唯一判别一条数据的情况
- 思路
- url数据持久化,存储在redis中,set
- 拿到url地址,判断在redis的url集合中是否存在
- 存在:说明已经请求过不在请求
- 不存在:没有请求过,请求,把URL存在redis的集合中
- 布隆过滤
- 使用多个加密算法加密url,得到多个值
- 往对应值的位置把结果设置为1
- 新来的一个url,一样通过加密算法生车某个值
- 如果对应的位置全为1,说明这个url地址已经抓过
- 否则没有抓过,就把对应位置的值设置为1
- 根据数据本身进行去重
- 选择特定的字段,使用加密算法(md5,sha1)将字段进行加密,生成字符串,存入redis集合中
- 后续新来一条数据,同样的方法进行加密,如果得到的字符串在redis中存在,说明数据存在,对数据进行跟新,否则说明数据不存在,直接插入
python 程序中使用 mongodb
pip install pymongo
from pymongo import MongoClient
class TestMongo(Object):
def __init__(self):
client = MongoClient(host=",port=27017)
self.collection = client["test"]["t1"]
def test_insert(self):
ret = self.collection.insert({"name":"xiaoyuan","age":45})
print(ret)
def test_insert_many(self):
item_list = [{"name":"test{}".format(i),"age":10.format(i)} for i in range(10)]
t = self.collection.insert_many(item_list)
for i in t.inserted_ids:
print(i)
|