Redis、MySQL、MongoDB相关面试题整理

第三部分 数据库和缓存(46题)
1.    列举常见的关系型数据库和非关系型都有那些?
    关系型数据库:通过外键关联来建立表与表之间的关系
    非关系型数据库:以对象的形式存储在数据库中,而对象之间的关系是通过对象自身的属性决定
    
    关系型数据库:MySQL、SQLite、Oracle
        优点:使用方便:通用的sql语言操作,易于维护
    
    非关系型数据库:Redis、MongoDB
        优点:读写性能很高,基于键值对存储,数据没有耦合性,容易扩展
    
2.    MySQL常见数据库引擎及比较?
    如何修改数据库引擎:
        方式一:修改my.ini文件,在最后一行追加default-storage-engine=InnoDB,然后重启服务
        方式二:在创建表的时候指定
                create table mytbl(
                    id int primary key,
                    name verchar(50)
                    )type=MyISAM
                
    InnoDB:支持事务,支持外键,支持行锁,mysql5.5后InnoDB是默认的引擎
            InnoDB适合频繁修改以及涉及到安全性较高的应用
            优点:支持事务,支持外键,并发量较大,适合大量update。
            缺点:查询数据相对较快,不适合大量的select。
            
    MyISAM:不支持事务,不支持外键,优势是访问速度快。
            对事务完整性没有要求或者以select,insert为主的应用基本上可以用这个引擎来创建表
            MYISAM的性能更优,占用的存储空间少
            优点:查询数据相对较快,适合大量的select,可以全文索引。
            缺点:不支持事务,不支持外键,并发量较小,不适合大量update
            
    Memory:Memory存储引擎使用存在于内存中的内容来创建表。每个memory表只实际对应一个磁盘文件,
            MEMORY类型的表访问非常得快,因为它的数据是放在内存中的,并且默认使用HASH索引。
            但是一旦服务关闭,表中的数据就会丢失掉
    Blackhole:任何写入到此引擎的数据均会被丢弃掉, 不做实际存储;Select语句的内容永远是空。
            充当日志服务器
            
    Merge: Merge引擎允许将一组使用MyISAM存储引擎的并且表结构相同的(字段顺序,字段名称,字段类型,索引定义顺序)的数据
            表合并成为一个表,方便数据查询
            
3.    简述数据三大范式?
    什么是范式:数据库设计对数据的存储性能,还有开发人员对数据的操作都有莫大的关系。所以建立科学的,规范的的数据库是需要满足一些规范的来优化数据数据
            存储方式。
    实体:表
    属性:表中的字段
    关系:表与表之间的关系
    第一范式(1NF):数据表的每一列(每个字段)必须是不可拆分的最小单元,也就是确保每一列的原子性;
    
    第二范式(2NF):满足1NF后,要求表中的所有列,都必须依赖于主键,而不能有任何一列与主键没有关系,也就是说一个表只描述
                一件事情:例如订单表只描述订单相关信息,所以每个字段都必须与订单id相关。
                
    第三范式(3NF):必须先满足2NF,要求:表中的每一列只与主键直接相关而不是间接相关。
                例如:订单表中需要客户信息,在分离出客户表后,订单表只需要一个客户id即可,而不能有其他客户信息。
    
    数据库的五大约束:
        1.primary key  :主键默认非空,只有主键才能设置自增,自增一定是主键,主键不一定自增
        2.unique         :设置唯一性约束,不能有重复值;unique(ip,port) 联合唯一, unique(id)
        3.default    
        4.not null        :设置非空约束,该字段不能为空;
        5.foreign key  : 只有innodb支持外键 constraint 外键名 foreign key(外键字段) references 参照表(参照字段) on                     delete cascade on update cascade   # 同步更新同步删除
        6.auto_increment: 标识该字段的值自动增长(整数类型,而且为主键)
        
        ps:unique + nut null == primary key
            unique 唯一的,可以为空
            primary key:唯一的,不可以为空
            
4.    什么是事务?MySQL如何支持事务?
    事务:事务用于将某些操作的多个sql语句作为原子性操作,一旦某个出现错误,即可回滚到原来状态,从而保证数据库的完整性。
    MySQL中只有使用了InnoDB的数据库或表才支持事务
    
5.    简述数据库设计中一对多和多对多的应用场景?
     一对多:学生与班级------一个学生只能属于一个班级,一个班级有多个学生
     多对多:学生和课程------一个学生可以选择多门课程,一个课程可以被多个学生选
     一对一:学生与学号------一个学生有一个学号,一个学号只属于一个学生
    
5.1 pymysql的使用?
    import pymysql
    # 连接
    conn = pymysql.connect(host=‘127.0.0.1‘,port=3306,user=‘root‘,password=‘‘,db=‘db1‘,charset=‘utf8‘)
    # 创建游标
    cursor = conn.cursor()
    sql = "select * from userinfo where username=‘%s‘ and pwd=‘%s‘" %(user,pwd) #%s加引号
    # 执行sql语句
    result = cursor.execute(sql)  # 执行SQL语句,返回的是受影响的行数
    print(result)
    # 关闭游标,关闭连接
    cursor.close()
    conn.colse()
    
    # execute() 之sql注入:
        # 1,用户名存在,绕过密码,在输入用户名的时候:yazhou‘ -- asfsfsdfsdfds
        在一条sql语句中如果遇到 select * from userinfo where username=‘yazhou‘ -- asfsfsdfsdfds‘ and pwd=‘‘
        则--之后的条件被注释掉了(注意--后面有一个空格)
        # 2。用户不存在,绕过用户名和密码,在输入用户名的时候:dfdsf‘ or 1=1 -- (注意--后有一个空格)
            select * from userinfo where username=‘dfdsf‘ or 1=1 -- ‘ and pwd=‘‘
    # 解决办法
        原来我们是对sql进行字符串的拼接,现在我们改写为:
        sql = ‘select * from userinfo where name=%s and password=%s‘     #%s不加引号
        result = cursor.execute(sql,[user,pwd])  #pymsql模块自动帮我们解决sql注入问题
    
    # 增删改:conn.commit()
        在数据库里增删改的时候,必须要进行提交,否则不生效
    
    # 获取数据
        fetchone():获取下一行数据
        fetchall():获取所有数据
        fetchmany():获取多少行数据,fetchmany(4) 4行
        cursor.execute(sql,[user,pwd])
        cursor.fetchall()
        以上都是元组返回,只能看到每行的数据,却不知道每列代表什么,这是时候我们就可以用返回字典的方式:
        
        cursor = conn.cursor(cursor=pymysql.cursors.DicCursor) #在实例化的时候,将属性cursor设置为pymysql.cursors.DictCursor
        cursor.execute(sql,[user,pwd])
        rows = cursor.fetchmany(2)
        print(rows) # [{‘id‘: 1, ‘username‘: ‘mjj‘, ‘pwd‘: ‘123‘}, {‘id‘: 3, ‘username‘: ‘张三‘, ‘pwd‘: ‘110‘}]
                
6.    如何基于数据库实现商城商品计数器?
    create table product(
                id int primary key anto_incremtn,
                pname varchar(64),
                pcount int);
                
7.    常见SQL(必备)
    # 库的操作
    create database db1 charset utf8;    # 创建数据库并指定编码,默认utf-8
    show create database db1;            # 查看创建的数据库
    show databases;                        # 查看所有的数据库
    use db1;                            # 使用db1数据库
    select databases();                    # 查看当前所在的数据库
    alter database db1 charset gbk;    # 修改数据库编码
    drop database db1;                    # 删除数据库db1
    # 表的操作
        # 增
        create table t1(id int,name char(20));        # 创建t1表
        
        # 删
        drop table t1;                                # 删除表
        # 改
        alter table t1 modify name char(6);            # 修改表字段的属性
        alter table t1 change name NAME char(7);    # 修改表字段
        
        # 查
        show create table t1;                        # 查看创建的t1表
        show tables;                                # 查看当前库下所有的表
        desc t1;                                    # 查看t1表的详细信息
    # 记录的操作
        # 增
        insert t1(id,name) values(1,‘aaa‘),(2,‘bbb‘);    #给t1表插入多条记录
        insert t1 values(3,‘ccc‘);                        # 插入一条记录(不写表字段,则必须全部字段对应值)
        insert t1(id) values(‘4‘);                        # 只插入id,name默认为Null
        # 删
        delete from t1;                                    # 清空表中的记录,再插入,自增id从删除前最大id开始
        truncate table t1;                                # 自增id从0开始
        delete from t1 where id =2;                        # 删除id=2的记录
        # 改
        update t1 set name=‘ddd‘ where id=2;            # 将id=2的name改为ddd
        # 查
        select id from t1;                                # 值查看id
        select * from t1;                                # 查看所有字段
        
8.    简述触发器、函数、视图、存储过程?
    触发器:定制用户对表进行增删改操作时的前后行为,没有查询
        基本语法插入前:create trigger tri_before_insert_tb1 before insert on tb1 for each row
                        begin
                        end
        # 对用户表的after insert后记录一条日志,到userLog表中,用户表affirm enum(‘yes‘,‘no‘) 表示插入成功是否
        eg: delimiter //    # 修改定界符为//,默认为;
            create trigger after_user_insert after insert on user_tb for each row  # 触发器的名字为:after_user_insert,对user_tb表的
            begin
                if new.affirm = ‘yes‘ then  # 插入的时候用new对象,(对象可以直接取插入的值),更新删除的时候用old
                insert into userLog(u_name,u_reg_time) values(new.name,new.reg_time);
            end //  # 触发器结束
            delimiter;  # 再将定界符修改回来
        # 查看触发器
        select * from information_schema.TRIGGER\G;
        
    函数:mysql中提供了许多内置函数
        1.round(x,y)
        2.rand() # 返回0-1直接的随机数,floor(rand()*1000) 生产0-1000直接的整数
        3.聚合函数
            avg(col) 指定列的平均值
            count(col) 指定列中非Null的个数
            min(col) 指定列中最小值
            max(col)
            sum(col)指定列的所有值和
        4.字符串函数 char_length(str),
        5.日期函数
            slect now()  # 年月日时分秒
            select curdata() # 年与日
            select curtime() # 时分秒
        6.格式化
            selectdate_format(‘2009-10-11 22:23:11‘,‘str‘)
        7.MD5()
        8.声明一个变量
            set @variable_name = what;
            其中what可以是基本数据类型,也可以是select的语句结果
            eg:
                set @A = select sub_time from blog where id = 1;
                select @A;
            
    视图:通俗的讲,视图就是一条select语句执行后返回的结果集。是一种虚拟存在的表,逻辑表,本身不包含数据。
         create view view_name as SQL语句
         多次用同一个虚拟表做为子查询的时候,我们可以将其创建一个视图,用以后用
         # 创建使用视图
         select cname from course where teacher_id = (select tid from teacher where tname=‘李老师‘);
         create view teacher_view as select tid from teacher where tname=‘李老师‘;
         select cname from course where teacher_id=(select tid from teacher_view);
        
         # 修改视图的语句
         alter view teacher_view as select * from course where cid>3;
         # 删除视图
         drop view teacher_view;
         # 查看视图
         select * from information_schema.VIEWS
        
    存储过程:是存储在数据库目录中的一些声明性语句。java,python等可以调用存储过程。
        优点:
            1.存储过程有助于提高应用程序的性能,存储过程被编译后,mysql将其放入缓存
            2.减少与应用程序之间的流量,因为应用程序不必发送冗长的sql语句,只发存储过程的名字和参数接即可
            3.存储过程对应用程序可重用,透明。将数据库接口暴露给应用程序
            4.存储过程是安全的。数据库管理员向应用程序授予适当的权限
        缺点:
            1.大量使用存储过程,使用这些存储过程的每个连接的内存使用量大大增加
            2.很难调试存储过程
            3.开发和维护存储过程不容易。
        #创建一个存储过程:
            delimiter //
            create procedure b1()     # 存储过程的名字为b1
                begin
                select * from blog;  # 存储过程的主体,
                end //
            delimiter ;
        存储过程的调用:call b1();
        在python中调用:cursor.callproc(‘b1‘)
                        print(cursor.fetchall())
        
        #查看存储过程:show create procedure b1;
        eg: # 存储过程传参
            delimiter //
            create procedure b2(in n int)  # 需要传一个n为int的参数
                begin
                select * from blog where id=n;
                end //
            delimiter ;
        # 调用
        cursor.callproc(‘b2‘,(3))
        
    事务:事务用于将某些操作的多个sql作为原子性操作,一旦某个出现错误,即可回滚到原来状态,从而保证数据的完整性
        关系型数据库事务必须满足是个条件/特征:
                数据库系统必须维护事务的以下特性(简称ACID):

原子性(Atomicity)

一致性(Consistency)

隔离性(Isolation)

持久性(Durability)
        原子性:一个事务中的所有操作,要么全部完成,要么全部不完成
        一致性:事务前后,数据库完整性没有被破坏
        隔离性:数据库中允许多个并发事务同时对数据进行读取修改,隔离性防止多个事务交叉执行导致数据不一致
        持久性:事务处理后,对数据修改是永久的。
        
        begin或 start transaction ,开启一个事务
        commit 或commit work,提交事务,并对数据库永久修改
        rollback或rollback work,回滚会结束用户的事务,并撤销正在进行的所有未提交的修改
        eg:
            begin;
            insert into tb value(5);
            insert into tb value(6);
            commit;
            
            start transaction;
            insert into tb value(5);
            insert into tb value(6);
            rollback;
    
9.    MySQL索引种类
    #什么是索引:
        数据库中专门帮助用户快速查找数据的一种数据结构,类似于字典中的目录(查找字典内容的时候可以根据目录查找数据的位置,
        然后直接获取)
    #索引的作用:
                约束和加速查找
    #有无索引的区别:
            无索引:从前往后一条一条查找
            有索引:创建索引的本质,就是创建额外的文件(查询的时候,先去额外的文件中定位置,然后再去原始表中查询,但是创建索引越多,
                会对硬盘有所损耗,创建索引后必须命中索引才能有效,查询快,但是更新删除插入依旧慢
    #MySQL中的索引的存储类型有两种:
                BTREE:innoDB默认支持,btree是根据二分查找的
                HASH:查询单条很快(比btree都快),但是范围模糊查询不一定快,因为hash值是无序的
    #索引的缺点:
                创建和维护索引需要时间,随着数量的增多锁耗时也变多
                索引占用空间,大量的索引,索引文件可能比数据文件更快达到上限值
                当对表中的数据进行修改的时候,索引也要动态维护
    #使用原则:
              对经常更新的表避免使用过多的索引,对经常查询的表应创建索引
              数据量小的表最好不要建立索引
              在一同值多的列上(字段上)不要建立索引,比如学生表的性别,相反在同值少的字段上可建立索引
    # 索引的分类
    单列索引:
        普通索引:MySQL中基本索引类型,没有什么限制,允许在定义索引的列中插入重复值和空值,纯粹为了查询数据更快一点
                  仅有一个作用:加速查找。
            # 方法一 在创建表的时候,创建索引
            create table userinfo(
                            nid int not null auto_increment primary key,
                            name varchar(32) not null,
                            emial varchar(64) not null,
                            index ix_name(name));
            # 方法二 在创建表后用create创建索引
            create index ix_name on userinfo(name);  # create index 索引的名字 on 表名(列名)
            # 删除索引
            drop index ix_name on userinfo;   # drop index 索引的名字 on 表名
            # 查看索引
            show index from userinfo;   # show index from 表名
        唯一索引:索引列中的值必须是唯一的,但是允许为空值,
                  作用:加速查找和唯一约束(可含Null),
            # 方法一 在创建表的时候,创建索引
            create table userinfo(
                            id int not null auto_increment primary key,
                            name varchar(32) not null,
                            unique index ix_name(name));
            # 方法二 在创建表后用create创建索引
            create unique index ix_name on userinfo(name);  # create unique index 索引名 on 表名(列名)
            # 删除唯一索引
            drop unique index ix_name on userinfo;  # drop index 索引的名字 on 表名
        主键索引:是一种特殊的唯一索引,不允许有空值。
                  作用:加速查找和唯一约束(不含null)
            # 方法一 在创建表的时候,创建索引
            create table userinfo(
                            id int not null auto_increment primary key,
                            name varchar(32) not null,
                            unique index ix_name(name));
            # 方法二 在创建表后用create创建索引
            create unique index ix_name on userinfo(name);  # create unique index 索引名 on 表名(列名)
            # 删除唯一索引
            drop unique index ix_name on userinfo;  # drop index 索引的名字 on 表名
    联合索引:
        联合主键索引:
            create index name_email on userinfo(name,email);  # 最左前缀顺序为创建的顺,name,email
            # 组合索引最左前缀为name,在单列查询中的条件是最左前缀name,那么才使用索引,速度快,否则不使用索引
                eg:select * from userinfo email=‘[email protected]‘; # 不使用索引,
                   select * from userinfo name=‘heihei‘;          # 使用索引
            # 但是在使用组合索引的多列查询,不管顺序,都是使用索引查询,速度快
        联合唯一索引
        联合普通索引:
    全文索引:只有在MyISAM引擎上才能使用,只能在char,varchar,text类型字段上使用全文索引
    空间索引:
    
    索引(A,B)
    A 走索引,
    B 不走索引
    A,B 走索引
    B,A 走索引
    C,A 走索引
    C,B 不走索引
    
    索引注意事项:
        1.避免使用select *
        2.count(1),count(col) 代替 count(*)
        3.创建表的时候尽量用char代替varchar
        4.组合索引,代替多个单列索引
        5.使用join来代替子查询
    
    执行计划:
        explain + sql语句:用来显示sql执行的信息参数,根据信息可以做优化
        
10.    索引在什么情况下遵循最左前缀的规则?
    在使用组合索引的情况下,小遵循最左前缀规则:
    最左前缀匹配规则:mysql会一直向右匹配知道遇到范围查询(<,>,between,like)等就停止匹配。
        例如:a = 1 and b =2 and c > 3 and d = 4,如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果
        建立(a,b,d,c)的索引,那么都可以用到,
        
11.    主键和外键的区别?
    #主键
        定义:唯一标识一条记录,不能有重复的,不允许为空
        作用:用来保证数据完整性
        个数:主键只能有一个
    #外键
        定义:表的外键是另一表的主键, 外键可以有重复的, 可以是空值
        作用:用来和其他表建立联系用的
        个数:一个表可以有多个外键

12.    MySQL常见的函数?
    #聚合函数:
      AVG(col)返回指定列的平均值
      COUNT(col)返回指定列中非NULL值的个数
      MIN(col)返回指定列的最小值
      MAX(col)返回指定列的最大值
      SUM(col)返回指定列的所有值之和
    now()  #返回当前时间
    data_format(data,format)  # 格式化

13.    列举 创建索引但是无法命中索引的8种情况。
    1.如果条件中有or,即使其中有条件带索引,也不会使用(这也就是为什么少用or的原因)
        注意:要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引
    2.对于多列索引,不是使用的第一个,则不会生效
    3.link查询以%开头,(以%结尾的:索引可以使用)
    4.如果类型是字符串,那一定要在条件中将数据用引号引用起来。
    5.如果mysql估计使用全表扫描要比使用索引快,则不使用索引
    6.对小表查询
    7.单独引用联合索引里的非第一位置的索引列
    8.提示不使用索引
    
14.    如何开启慢日志查询?
    开启慢日志查询,可以让mysql记录下查询超过指定时间的语句,通过定位分析性能瓶颈,才能更好的优化数据库。
    # 查看是否开启慢日志
    show variables like ‘slow_query%‘;
        slow_query_log  # 慢日志开启状态,OFF为未开启,ON为开启
        slow_query_log_file # 慢日志的存放位置
    # 查看慢日志超时时间
    show variables like ‘long%‘;
        long_query_time # 默认10秒,查询超过多少秒才记录
    # 开启慢日志(方式一)
    set global slow_query_log=1;
    # 再次查看
    show varibales like ‘slow_query_log%‘;
    
    # 开启慢日志(推荐方法)
    在my.conf文件中找到[mysqld],在其下面添加:
        slow_query_log=1
        slow_query_log_file=‘目录‘
        long_query_time=1
        
15.    数据库导入导出命令(结构+数据)?
    mysqldump -u root mytest > mytest.sql -p  # 数据表结构+数据
    mysqldump -u root -d mytest > mytest.sql -p  #数据表结构
    
    导入:
        1.创建一个新数据库
            create database test_db;
        2.将备份的文件导入到test_db数据库中
            mysql -u root test_db < mytest.sql -p
        
        2.1 在mysql的库中导入
            source mytest.sql
    
16.    数据库优化方案?
    1.避免使用全表扫描,首先应考虑在where及order by涉及的col上建立索引
    2.尽量避免在where字句中对字段进行null判断,否则导致引擎放弃使用索引,而进行全表扫描
        最好也不要给数据库留NULL,竟可能使用Not null
    3.很多时候用exists代替in是一个好的选择
    4.索引并不是越多越好
    5.使用join来代替子查询
    6.使用事务
    7.使用外键
    8.使用索引
    9.优化查询语句
    
17.    char和varchar的区别?
    1.数字
        整数:int(n), 4字节32位,int类型后面的存储是显示宽度,而不是存储宽度
            为int指定宽度,仅仅是查询结果的显示宽度,与存储范围无关
        小数:
            float(M,D):M是整数部分总个数,D是小数点后个数,M最大值为255,D最大值为30
            double(M,D):M是整数部分总个数,D是小数点后个数。M最大值为255,D最大值为30
            decimal(M,D):M是整数部分总个数(负号不算),D是小数点后个数。 M最大值为65,D最大值为30。
            create table t5(x float(255,30);  # D和M不能超过最大值
            create table t6(x double(255,30); # D和M不能超过最大值
            create table t7(x decimal(65,30); # D和M不能超过最大值
            insert into tx values(1.1111111111111111111111111111111); # 同样给t5,t6,t7出入相同的数据,t7的精确度最高
            
    2.字符串
        char(10):简单粗暴,浪费空间,存取速度快,范围0-255
                指定长度为10,存> 10的报错,存<10个字符的则用空格填充(右填充)直到10个字符存储
                但是在查询的时候,会删除尾部的空格,不会显示填充的空格
                
        varchar(10):变长,精准,节省空间,存取速度慢,范围0-65535
                存储数据的真实内容,不会用空格填充,例如‘ab ‘,尾部的空格也会被存起来
                强调:varchar类型会在真实数据前加1-2bytes的前缀,该前缀用来表示真实数据的bytes字节数。
                    真实数据<255bytes,则需要1bytes
                    真实数据>255bytes,则需要2bytes
                    
            char的存储方式是:对英文字符(ASCII)占用1个字节,对一个汉字占用两个字节;
            varchar的存储方式是:对每个英文字符占用2个字节,汉字也占用2个字节。
        text:用于保存变长的大字符串,65535
        
    3.时间类型
        data    :YYYY-MM-DD
        time    :HH:MM:SS
        year    :YYYY
        datetime(常用):YYYY-MM-DD HH:MM:SS   1001-9999  存储空间为4字节
        create table t9(d date,t time,dt datetime);
        insert into t9 values(now(),now(),now());   # mysql 自带now函数
        注意:
            单独插入时间时,需要以字符串形式,插入
            插入年份时候,尽量使用4位值
            插入两位年份时,<=69,以20开头,比如50,结果是2050
                           >=70,以19开头,比如71,结果1971
        
        date_format()函数用于以不同的格式显示日期时间数据:
            data是合法的日期,format是规格时间的格式
            data_format(now(),‘%Y-%m-%d %H:%i:%s‘)
        
    4.枚举和集合类型:
        枚举:sex enum(‘male‘,‘female‘,‘other‘)           #在指定范围内,多选一
        集合:favorite set(‘play‘,‘music‘,‘read‘,‘study‘)  #在指定范围内,多选多
        
18.    简述MySQL的执行计划?
    执行计划:explain + sql语句
    id    select_type    table type possible_keys key key_len ref rows extra
    参数说明:
        id:
            id相同:执行顺序由上至下
            id不同:如果是子查询,id的序号是递增的,id值越大优先级越高,越先被执行
            id相同又不同:id相同,认为是一组,从上到下执行,id越大越先被执行
        select_type:查询类型
            simple 简单查询,查询中不含子查询或union
            primary 最外层开始查询,查询总包含了任何复杂的子部分
            subquery:在select或where中含有子查询
            derived:
            union   联合
        table:正在访问的表名
        type:SQL查询优化中一个很重要的指标,结果从好到坏
            system >const>eq_ref>ref>index_merge>range>index>all
            一般来说好的sql查询要达到range以上,最好能达到ref
            syetem:系统表中只有一行,特例,忽略
            const:通过索引一次就找到了,
        possible_keys:可能使用的索引
        key:真实使用的
        key_len:索引字节长度
        ref:显示索引的那一列被使用了
        rows:估计为了找到所需的行而要读取的行
        extra:不适合在其他字段中显示,但是十分重要的额外信息
            
19.    在对name做了唯一索引前提下,简述以下区别:
        select * from tb where name = ‘Oldboy-Wupeiqi’
        select * from tb where name = ‘Oldboy-Wupeiqi’ limit 1
    
    区别是:第一条需要遍历整个数据表,而第二条找到一个就返回
    
20.    1000w条数据,使用limit offset 分页时,为什么越往后翻越慢?如何解决?
    select * from userinfo limit 0,10;
    select * from userinfo limit 10,10;
    select * from userinfo limit 20,10;
    ……
    select * from userinfo limit 1000w,10;
    越往后,需要的时间就越长。是因为越往后查,全文扫描查询,回去数据库表中扫描数据。
    limit10000,20的意思扫描满足条件的10020行,扔掉前面的10000行,返回最后的20行,问题就在这里。
    
    优化方案:
        情况1:只有上一页和下一页的情况
             # 下一页,当前页最大id是299980,最小id是299971
             select * from userinfo where id> max_id limit 10;
             # 下一页,当前页最大id是299980,最小id是299971
             select * from userinfo where id <min_id order by id desc limit 10;
             select * from (select * from where id<min_id order by id desc limit 10) as A order by id asc;
        情况二:有中间页面的情况
           select * from userinfo where id in(
               select id from (select * from userinfo where id > pre_max_id limit (cur_max_id-pre_max_id)*10) as A order by A.id desc limit 10
           );    
           
21.    什么是索引合并?
    MySQL5.0之前,一个表一次只能使用一个索引,无法同时使用多个索引分别进行条件扫描。但是从5.1开始,
    引入了 index merge 优化技术,对同一个表可以使用多个索引分别进行条件扫描。
    eg:
        SELECT * FROM tbl_name WHERE key1 = 10 OR key2 = 20;
        SELECT * FROM tbl_name WHERE (key1 = 10 OR key2 = 20) AND non_key=30;
    索引合并:对多个索引分别进行条件扫描,然后将它们各自的结果进行合并
        1.是把几个索引的范围扫描合并成一个索引
        2.索引合并的时候,会对索引进行并集,交集,以便合并成一个索引
        3.需要合并的索引只能是一个表的,不能对多表进行索引合并
    怎么确认使用了索引合并:
        explain + sql:会在输出的type中显示index_merge,key列显示所使用过的索引
        
22.    什么是覆盖索引?
    覆盖索引:覆盖索引是select的数据列只用从索引中就能够取得,不必读取数据行,换句话说查询列要被所建的索引覆盖。
        
    举一个简单的例子:
        create index index_name on tb_user(name);   # 对表name字段建立索引
        select count(name) from tb_user;            # 查询name字段,就是覆盖索引了
        # 因为select的数据列只从索引中就能取得,不必进行读取数据行。
        explain select count(name) from tb_user;   # 执行计划中可以看到Extra:Using index 就表示在使用索引覆盖
        
23.    简述数据库读写分离?
    读写分离:
        让主数据库处理事务性查询,而从数据库处理select查询
    好处:增加冗余,增加了机器的处理能力,对于读操作为主的数据库,使用读写分离是最好的场景
    读写分离高性能的原因:
        1.物理服务器增加,负荷增加
        2.主从只负责各自的写和读操作,
        3.从库可以配置为MyISAM引擎,提升查询性能
        
24.    简述数据库分库分表?(水平、垂直)
    关系型数据库比较容易成为系统的瓶颈,当表达到1000W或100G后,即使进行优化,很多操作蚁人性能底下。
    此时就要考虑数据库切分了。切分的目的是减少数据库负担,缩短查询时间。
    
    数据库分布式核心内容无非就是数据切分,以及切分后对数据的定位,整合。
    数据切分就是将数据分散存储到多个数据库中,使得单一的数据库中的数据量变小,通过扩充主机的数量缓解
    单一数据库的性能问题,而达到提升数据库操作性能的目的。
    
    数据库切分根据切分类型:分为垂直(纵向)和水平(横向)切分
    
    垂直切分:常见有垂直分库,垂直分表两种。
        垂直分库:根据业务的耦合度,将关联度低的不同表存储在不同的数据库中。
        垂直分表:是基于数据库中的列,某个表的字段比较多,可以新建一张扩张表,将经常不用的字段或者字段长度达的字段拆分出去。
    水平切分:当一个应用难以在细粒度垂直切分的时候,或切分后数据量行数巨大等。
        库内分表:
        分库分表:是根据表内数据内在的逻辑关系,将同一张表按不同的条件分散到多个数据库或多个表中。每张表
                只包含一部分数据,从而使得单个表的数据量变小,到达分布的效果。
        
25.    redis和memcached比较?什么是redis?
    redis具有丰富的数据类型,memcached只有简单的字符串
    redis不仅仅支持简单的k/v类型数据,同时还提供list,set,hash等数据结构的存储,
    redis支持数据备份,redis支持数据的持久化,可以将内存中的数据保存到磁盘中,重启的时候再次加载使用
    memcachd挂掉后,数据不可恢复,redis挂掉后可以通aof恢复
    memcached支持多线程,redis单线程操作。
    redis的查询速度比memchached快的多
    
    redis是一个基于内存的高性能k-v数据库,Remote Dictionary Server(远程字典服务)
    
26.    redis中数据库默认是多少个db 及作用?
    redis下,数据库是由一个整数索引标识,而不是由一个数据库名称
    数据库的数量是可以配置的,默认情况下是16个(0-15)。修改/etc/redis/redis.conf下的databases = 16,指令:databases 64
    默认连接的是index= 0的数据库,着16个库相互之间是独立的。类似于mysql服务器里的多个数据库
    不同的应用程序数据存储在不同的数据库下。可以通select num来切换数据库
    
27.    python操作redis的模块?
    import redis
    conn = redis.Redis(host=‘192.168.11.254‘,port=6379)
    # 字符串
    conn.set(‘key‘,‘value‘)
    conn.get(‘key‘).decode(‘utf-8)
    
    # 给字典设置和获取值
    conn.hset(‘键值1‘,‘键值2’,‘value’)
    conn.hget(‘键值1‘,‘键值2’)
    conn.hgetall(‘键值1‘)     #获取所有键值1的数据
    conn.hdel(‘键值1‘,‘键值2’) # 删除键值2的值
    # 其他用法
    conn.keys(‘user1*‘)  # #获取用户1的所有的key
    conn.expire(键值1,timeout)   #给键值1 设置一个超时时间,单位秒,过期自动删除
    conn.flushall()    # 清空
    conn.exists(key)   #判断键值是否存在
    
28.    如果redis中的某个列表中的数据量非常大,如果实现循环显示每一个值?
    def list_iter(name):
        """
        先取得列表的长度,在for循环长度,通过lindex对列表取值,返回yield
        name:redis中的列表的key
        返回列表元素
        """
        list_count = r.llen(name)    # llen() 获取列表长度
        for index in range(list_count):
            yield r.lindex(name,index)   # lindex(naem,index)  通过索引找元素
            
29.    redis如何实现主从复制?以及数据同步机制?
    在redis中,用户可以通过执行slaveof命令,让一个服务器去复制另一个服务器,我们称呼被赋值的服务器为master
    主服务器,而对主服务器进行复制的服务器称为从服务器。
    redis1:127.0.0.1:6379
    redis2:127.0.0.1:23456
    
    127.0.0.1:23456> slavefo 127.0.0.1 6379
    
    同步机制:
        同步:当从服务器发送slaveof命令后,从服务器首先需要执行同步操作,将从服务器的数据库状态更新到主服务器所在的数据库状态。
        命令传播:在执行完同步操作后,如果后续主服务器数据库状态变化,主服务器需要对从服务器进行命令传播操作:
                    主服务器会将自己执行过的命令(也就是造成主从不一致的命令),发送给从服务器,从服务器再执行,就同步了
                    
30.    redis中的sentinel的作用?
    sentinel是redis官方推荐的高可用性(HA)解决方案。
    Master-slave,master宕机,slave自动切换为master
        不时地监控redis是否按照预期良好地运行;
        能够进行自动切换,当一个master节点不可用时
        
31.    如何实现redis集群?
    1.安装集群软件    
        # EPEL源安装ruby支持
        yum install ruby rubygems -y
        # 使用国内源
        gem sources -a http://mirrors.aliyun.com/rubygems/
        gem sources  --remove http://rubygems.org/
        gem sources -l
        gem install redis -v 3.3.3

2、redis配置文件
        port 7000
        daemonize yes
        pidfile /data/7000/redis.pid
        logfile "/var/log/redis7000.log"
        dbfilename dump.rdb
        dir /data/7000
        cluster-enabled yes # 开实例的集群模式
        cluster-config-file nodes.conf # 保存节点配置文件的路径
        cluster-node-timeout 5000
        appendonly yes

启动6个节点(要让集群正常运作至少需要三个主节点,另外三个做为从节点)    
        /application/redis/src/redis-server /data/7000/redis.conf
        /application/redis/src/redis-server /data/7001/redis.conf
        /application/redis/src/redis-server /data/7002/redis.conf
        /application/redis/src/redis-server /data/7003/redis.conf
        /application/redis/src/redis-server /data/7004/redis.conf
        /application/redis/src/redis-server /data/7005/redis.conf

  ps -ef |grep 700

创建集群    
        /application/redis/src/redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 \
        127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
        # 选项–replicas 1 表示我们希望为集群中的每个主节点创建一个从节点
        # 之后跟着的其他参数则是这个集群实例的地址列表,3个master3个slave redis-trib 会打印出一份预想中的配
        # 置给你看, 如果你觉得没问题的话, 就可以输入 yes
        1

32.    redis中默认有多少个哈希槽?
    16384,使用哈希槽的好处是可以方便的添加或删除节点。
    当需要在redis集群中放置一个k-v时候,然后通过对key进行CRC16校验后和16384取模
    来计算放置在哪个槽里。
    
33.    简述redis的有哪几种持久化策略及比较?
    Reids提供两种持久化方法:
    1.Redis DataBase(RDB)
        在不同的时间点,将redis存储的数据生成快照并存储在磁盘上。redis会单独fork一个子程序来进行持久化,主进程不会
        进行任何IO操作,这样就确保了redis极高的性能。。RDB是每隔多长时间持久化一次
    2.Append-only File(AOF)
        将redis执行过的所有写指令都记录下来,在下次redis启动的时候,只需要把这些指令从前到后执行一遍就可以
        实现了数据的恢复。。AOF的持久化策略是每隔一秒把缓存中的写指令记录到硬盘中。
    
    如果要进行大规模的数据恢复,且对数据恢复的完整性不是非常敏感,那么RDB要比AOF更加高效。
    如果对数据完整性非常敏感,那么就用AOF
    
34.    列举redis支持的过期策略。
    三种过期策略:
        1.定时删除
            含义:在设置key的同时,为改key设置一个定时器,让定时器在key的过期时间来临时,对key进行删除
            优点:保证内存尽快被释放
            缺点:若key很多,删除会占用很多CPU时间;定时器的创建耗时,影响性能
        2.惰性删除
            含义:key过期的时候不删除,每次从数据库获取key的时候去检测是否过期,若过期,则删除,返回Null
            优点:删除操作只发生在从数据库中取出key的时候,
            缺点:若大量的key在超时候,很久一段时间内,都没有被获取过,那么可能发生内存泄漏(无用的垃圾占大量内存)
        3.定期删除
            含义:每隔一段时间删除过期的key操作
            优点:通过限制删除操作的时长和频率,来减少对CPU时间占用--处理定时删除的缺点
                  定期删除过期的key--处理惰性删除的缺点
            缺点:在内存友好方面不如定时删除
                  在cpu时间友好方面,不如惰性删除
            难点:合理的设置删除操作的时长(每次删除多长时间)和执行的频率(每隔多长时间做一次删除)

35.    MySQL 里有 2000w 数据,redis 中只存 20w 的数据,如何保证 redis 中都是热点数据?
    #redis 提供 6种数据淘汰策略:
        voltile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
        volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
        volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
        allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
        allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
        no-enviction(驱逐):禁止驱逐数据

redis内存数据级上升到一定大小时,就会实行数据淘汰策略,
    从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
    
36.    写代码,基于redis的列表实现 先进先出、后进先出队列、优先级队列。
    1、FIFO队列:
        class FIFO():
            # lpush(‘list‘,val)进入--->[4,3,2]---> rpop(‘list‘)
            def __init__(self,conn):
                self.conn = conn
            def push(self,vla):
                self.conn.lpush(‘list‘,val)
            def pop(self):
                return self.conn.rpop(‘list‘)
    2.后进先出队列:
        class zhan():
            def __init__(self,conn):
                self.conn = conn
            def push(self,val):
                self.conn.rpush(‘list‘,val)
            def pop(self):
                return self.conn.rpop(‘list‘)
    3.优先级队列:
        class Prioriy():
            def __init__(self,conn):
                self.conn = conn
            def push(self,val,count):
                self.conn.zadd(‘list‘,val,count)
            def pop(self):
                a = self.conn.zrange(‘list‘,0,-1)[0]
                self.conn.zrem(‘list‘,a)
                return a
                
37.    如何基于redis实现消息队列?
    1.什么是消息队列?
        一个消息的链表,是一个异步处理数据的处理引擎
    2.有什么好处?
        不能能够提高系统负荷,还能够改善因为网络阻塞导致的数据缺失
    3.用途有哪些?
        邮件发送,日志存储,订单生成,
    4.有哪些软件?
        redis。。。。
    5.怎么实现?
        顾明思议,先入队,后出队;先把数据放到消息队列中(入队),后根据相应的key获取数据(出队)
    6.Redis可以做消息队列?
        首先,redis设计用来做缓存的,但是由于它自身的某种特性使得它可以用来做消息队列,它有几个阻塞的api可以使用
        这些阻塞的api让其有能力做消息队列;做一个消息队列的其他特性如FIFO也很容易,只需要一个list对象从头取数据,从尾
        部塞数据即可;redis能做消息队列还得益于其list对象blpop,brpop接口以及pub/sub(发布/订阅)的接口,它们都是阻塞
        的。
    redis提供了两种方式来作为消息队列:
        1.生产者消费者模型:会让一个或多个客户端去监听消息队列,一旦消息到达,消费者马上消费(谁先抢到算谁的),
                            没有消息,继续监听
        2.发布订阅者模型:也会让一个或多个客户端订阅消息频道,只要发布消息,所有的订阅者都能收到消息,订阅者都是平等的
    
38.    如何基于redis实现发布和订阅?以及发布,订阅和消息队列的区别?
    Redis自带有PUB/SUB机制,即是发布-订阅模式。这种模式生产者和消费者是1-M的关系,即一条消息会被多个消费者消费,当
    只有一个消费者的时候就是1-1的消息队列了。
    pub/sub机制模型如下:publish是生产者,channel可以看做是一个发布消息的频道,只要client订阅(subscribe)了这个频道
    ,就能获取此频道的消息了
                                    client1
        publish ------> channel---->client2
                                    client3
    发布者和订阅者都是redis client端,channel是redis 服务端。发布者将消息发布到某个频道,订阅了这个频道的订阅者就能够收
    到消息。
    发布消息:publish first ‘hello‘     # 在first频道发布hello消息,其返回值为接收到该消息的订阅者的数量。
              publish second ‘hello‘    # 在second频道发布hello消息,其返回值为接收到该消息的订阅者的数量。
    订阅某个频道:
              subscribe first second    # 订阅了两个频道,其返回值包括客户端订阅的频道,目前已订阅的频道数量,
                                        # 以及接收到的消息

39.    什么是codis及作用?
    codis是一个分布式redis解决方案

40.    什么是twemproxy及作用?
    twemproxy是一个memcached,redis的轻量级代理。有了twemproxy,客户端不用直接访问redis服务器,
    而是通过twemproxy代理间接访问。
    主要用于管理 Redis 和 Memcached 集群,减少与Cache 服务器直接连接的数量。
    
41.    写代码实现redis事务操作。
    一般来说,事务有四个性质称为ACID,分别是原子性,一致性,隔离性和持久性。

a)原子性atomicity:redis事务保证事务中的命令要么全部执行要不全部不执行。有些文章认为redis事务对于执行错误不回滚违背了原子性,是偏颇的。

b)一致性consistency:redis事务可以保证命令失败的情况下得以回滚,数据能恢复到没有执行之前的样子,是保证一致性的,除非redis进程意外终结。

c)隔离性Isolation:redis事务是严格遵守隔离性的,原因是redis是单进程单线程模式,可以保证命令执行过程中不会被其他客户端命令打断。

d)持久性Durability:redis事务是不保证持久性的,这是因为redis持久化策略中不管是RDB还是AOF都是异步执行的,不保证持久性是出于对性能的考虑。
    # 应用场景,如银行转账,等
    import redis
    pool = redis.ConnectionPool(host=‘127.0.0.1‘,port=6379)
    conn = redis.Redis(connection_pool=popl)
    # transaction默认为False,只可以完成批量提交的作用,节省网络延时
    # 改为True后可以实现事务功能
    pipe = conn.pipeline(transaction=True)
    # 开始事务
    pipe.multi()
    pipe.set(‘name‘,‘zhangsan‘)
    pipe.set(‘role‘,‘manager‘)
    pipe.set(‘age‘,19)
    
    pipe.execute()    # 提交
    # 用电商去库存,秒杀的时候举例
    redis的事务可以认为是一段命令的批量执行和一次返回,事务操作本身没有问题,执行过程也不会中断。
    但是在pipe.execute()的时候事务才真正的向redis_server提交,但是遗憾的是在redis_server执行之前
    都有机会被其他用户修改,完全起不到锁库存的概念。
    
42.    redis中的watch的命令的作用?
    # 用电商去库存,秒杀的时候举例
    redis的事务可以认为是一段命令的批量执行和一次返回,事务操作本身没有问题,执行过程也不会中断。
    但是在pipe.execute()的时候事务才真正的向redis_server提交,但是遗憾的是在redis_server执行之前
    都有机会被其他用户修改,完全起不到锁库存的概念。
    
    watch可以看做数据库中的乐观锁的概念。
    watch可以监控一个或多个键,一旦其中有一个键被修改、删除,之后事务就不在执行。
    监控一直持续到exec命令。修改人保证自己的watch数据没有被其他人修改,否则自己就修改失败。
    
    这里的watch相当于一个锁的。
    
    如果在watch后值被修改,在执行pipe.execute()的时候会报异常WatchError: Watched variable changed.
    
    # 代码实现
    if __name__ == "__main__":
        whit sms_redis.pipeline() as pipe:
            while 1:
                try:
                    # 关注一个key
                    pipe.watch(‘stock_count‘)
                    count = int(pipe.get(‘stock_count‘)
                    if count > 0:    # 有库存
                        # 事务开始
                        pipe.multi()
                        pipe.set(‘stock_count‘,count-1)
                        # 事务结束
                        pipe.execute()
                    break
                execpt Exception:
                    traceback.print_exc()
                    continue
                    
43.    基于redis如何实现商城商品数量计数器?
            if __name__ == "__main__":
            whit sms_redis.pipeline() as pipe:
                while 1:
                    try:
                        # 关注一个key
                        pipe.watch(‘stock_count‘)
                        count = int(pipe.get(‘stock_count‘)
                        if count > 0:    # 有库存
                            # 事务开始
                            pipe.multi()
                            pipe.set(‘stock_count‘,count-1)
                            # 事务结束
                            pipe.execute()
                        break
                    execpt Exception:
                        traceback.print_exc()
                        continue
                        
44.    简述redis分布式锁和redlock的实现机制。
    为redis集群设计锁,防止多个任务同时修改数据库,其本质就是为了集群中的每一个主机设置一个
    会超时的字符串,当集群中有一半多的机器成功后就认为加锁成功,直至锁过期。
    
45.    什么是一致性哈希?Python中是否有相应模块?
    分布式算法:在做服务器负载均衡的时候可以选择的负载均衡算法有很多:
        轮询,哈希,最少连接算法,响应速度算法,加权算法等等,其中哈希最长用。
    典型应用场景:有N台服务器提供缓存服务,需要对服务器进行负载均衡,将请求平均分配到每台服务器上。
    
    常用的算法是对hash结果取余(hash() mod N):对机器标号0-(N-1),按照自定义的算法,对每个请求的hash()值按N去模,
    得到余数i,然后将请求分配到编号为i的机器上。这种算法存在致命问题,如果有服务器宕机,那么落在该服务器上的请求,无法得到正常
    处理。这时需要将宕掉的服务器去掉,此时会有缓存数据需要重新计算,如果新增服务器,也需要对缓存数据进行重新计算。
    对于系统而言,这是不可接受的颠簸。
    
    from hash_ring import *
    redis_server = [‘192.168.0.246:11212‘,
                    ‘192.168.0.247:11212‘,
                    ‘192.168.0.249:11212‘]
    ring = HashRing(redis_server)
    server = ring.get_node(‘my_key‘)
    print(server) # ‘192.168.0.247:11212‘
    server = ring.get_node(‘my_keysdfsdf‘)
    print(server)  # ‘192.168.0.249:11212‘
    
46.    如何高效的找到redis中所有以oldboy开头的key?
    import
    conn = redis.Redis(host=‘192.168.11.254‘,port=6379)
    conn.keys(‘oldboy*‘)

47.redis列表命令?
    blpop: # 命令移出并获取列表的第一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。 (kay,value)
    brpop: # 命令移出并获取列表的最后一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。 值同上
    lindex # 通过索引获取列表中的元素,0,1,2,……也可以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素
    llen: # 获取列表长度
    lpop: # 命令用于移除并返回列表的第一个元素。
    rpop: # 命令用于移除并返回列表的最后一个元素。
    lpush:# 命令将一个或多个值插入到列表头部。 如果 key 不存在,一个空列表会被创建并执行 LPUSH 操作
    rpush:# 命令用于将一个或多个值插入到列表的尾部(最右边)。 如果列表不存在,一个空列表会被创建并执行 RPUSH 操作
    lpushx: # 将一个值插入到已存在的列表头部,列表不存在时操作无效。
    rpushx:    # 命令用于将一个值插入到已存在的列表尾部(最右边)。如果列表不存在,操作无效。rpush mylist ‘hello‘
    lrange: # 返回列表中指定区间内的元素,区间以偏移量 START 和 END 指定。 其中 0 表示列表的第一个元素, 1 表示列表的第二个元素,以此类推。 你也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。
    zrange: # 如果你需要以成员的值递减来排序,请使用zrange,下标参数start和stop都是以0为底,也就是说,以 0 表示有序集第一个成员,以 1 表示有序集第二个成员
        eg:zrange(‘list‘,0,-1,id)  # 按照id从大到小。排序
        
48.MongoDB和MySQL直接最基本的区别是什么,什么是MongoDB?
    关系型数据库和非关系性数据库的区别,MongoDB是一个基于分布式文件存储的数据库,是非常灵活的数据库。MongoDB 文档类似于 JSON 对象
    MongoDB的特点是什么?
    (1)面向文档(2)高性能(3)高可用(4)易扩展(5)丰富的查询语言
    
    MySQL    MongoDB
    DB          DB               数据库
    Table      Collection      Table概念
    Row          Document        Row概念
    Field      Field              字段概念
                _id              唯一概念,自动生成
                
    MongoDB是基于文档存储的,基于关系型和非关系型数据库之间的产品。它支持的数据结果非常松散,类似于json。。
    可以存储比较复杂的数据。
    
49.MongoDB要注意的问题

1 因为MongoDB是全索引的,所以它直接把索引放在内存中,因此最多支持2.5G的数据。如果是64位的会更多。

2 因为没有恢复机制,因此要做好数据备份
    
    3.默认监听地址是127.0.0.1,port是27017
    
50.MongoDB基本指令
    show dbs    #查看所有数据库
    use s11db    #创建或使用数据库
    db            #查看当前所在的数据库
    show tables    #查看当前数据库的表
    show collections    #查看当前数据库的表
    
    # 增加
    db.user.insertOne({‘name‘:‘xiaoming‘,‘age‘:12})  #只能写字典
    db.user.insertMany([{‘name‘:‘xiaoming‘,‘age‘:12},{‘name‘:‘xiaohua‘,‘age‘:14}]) #只能写列表套字典
    
    # 删
    db.user.remove({‘name‘:‘xiaoming‘})  # 删除符合的row
    db.user.deleteOne({‘name‘:‘xiaoming‘}) # 删除符合的row
    db.user.deleteOne({name:‘alex_sb‘,age:32})  # 逗号相当于AND
    db.user.deleteMany({name:‘alex_sb‘}) #删除所有符合的
    db.user.deleteMany({})   #清空数据
    # 查
    db.user.find()    # 查询所有
    db.user.findOne({"age":12})  # 等于12的
    db.user.findOne({"age":{$gt:12}}) # 查询age大于12的
    db.user.findOne({‘name‘:‘xiaoming‘,"age":{$gt:12}})
    # 改
    db.user.update({‘name‘:‘xiaoming‘},{$set:{‘name‘:‘老坛酸菜‘}})  # 把名字为xiaoming的改为老坛酸菜
    db.user.update({‘name‘:‘xiaoming‘},{$set:{‘sex‘:‘男‘}})  # 给名字为xiaoming的增加一个属性sex并设置值
    db.user.updateOne({‘name‘:‘xiaoming‘},{$set:{‘name‘:‘lisi‘}})    #符合条件的第一条数据
    db.user.updateOne({‘name‘:‘xiaoming‘},{$set:{‘name‘:‘lisi‘}})    #符合条件的第一条数据
    
    修饰器:
    $set:将某个key的value修改为某个值,或增加属性  # {$set:{‘name‘:‘alex_sb‘}}
    $unset: 删除字段   {$unset:{test:""}}    #db.user.updateOne({"name":"alex"},{$unset:{"age":""}})
    $lt,$lte,$gt,$gte……   #数学比较符
    $:代指符合条件的某个数据对象,仅仅是查询的第一条数据
    $inc:db.user.updateMany({},{$inc:{‘age‘:100}})#给所有的age加100,就算Document没有age字段也会按照初始零去相加
    Array:
        $push:向Array数据后面追加一个元素{$push:{‘name‘:‘alex‘}}
        $pull:删除数组中的某一个元素 {$pull:{‘hobby‘:‘basketball‘}}
        $pop:删除数组的第一个或最后一个
            {$pop:{‘hobby‘:1}}  删除hobby数组最后一个
            {$pop:{‘hobby‘:-1}} 删除hobby数组第一个
    查询$关键字:
        $in: 查询字段符合in中的数值  db.user.find(age:{$in:[11,12,13,14]})
        $or:    db.user.find({$or:[{age:1},{age:2}]})
        $all:   db.user.find({test:{$all:[2,1]}})   # array元素相同即可,包含即可。。。all的值是test的子集
    排序:
        db.user.find({}).sort({age:1}) #1升序(asc),-1降序(desc)
    显示条目:
        db.user.find({}).limit(2)# 只显示前两条
    跳过:
        db.user.find({}).skip(2)#从第三条开始显示
    
    db.user.find({}).sort(‘age‘:1).skip(1).limit(2) # 可以做分页
    
    
    删除表:db.表名.drop()

51.MongoDB的数据类型:
    string
    integer
    double 包含float,MongoDB不存在Float类型,默认就是double
    Null  空数据类型
    Data
    Timestamp
    ObjectID    "_id" : ObjectId("5b98709cb001ec5a59c6f78e"), Documents自动生成的 _id
        
52.python使用MongoDB
    import pymongo
    from bson import ObjectId
    
    mclient = pymongo.MongeClient(host=‘127.0.0.1‘,port=27017)
    mongo_db = mclient[‘s11db‘]  # 连接或创建数据库
    其他用法和在mongo中用法基本一样,有微小差别:
    insertOne -- > insert_one    # 其他操作一样
    {$set:{‘sex‘:‘男‘}} --->    {"$set":{‘sex‘:‘男‘}}
    mongo_db.user.find({}).sort(‘age‘,pymongo.DESCENDING)  # 降序排序
    mongo_db.user.find({}).sort(‘age‘,pymongo.ASCENDING)  # 升序排序
    
    其他一样

原文地址:https://www.cnblogs.com/yazhou-lai/p/9763501.html

时间: 2024-11-04 17:23:41

Redis、MySQL、MongoDB相关面试题整理的相关文章

基于Redis+MySQL+MongoDB存储架构应用

摘  要: Redis+MySQL+MongoDB技术架构实现了本项目中大数据存储和实时云计算的需求.使用MongoDB切片的水平动态添加,可在不中断平台业务系统的同时保障扩容后的查询速度和云计算效能:依据切片键索引分片,位于各切片独立进行计算,使大数据下的实时分析成为现实.对于高频访问的数据放在了Redis中,有效地降低磁盘I/O,使业务系统响应更为敏捷,满足了高并发下应用服务的高呑吐要求. 关键词: 移动位置服务SaaS:Redis:MongoDB 基于移动位置服务的应用是根据用户所在位置提

一文教您如何通过 Docker 快速搭建各种测试环境(Mysql, Redis, Elasticsearch, MongoDB) | 建议收藏

原文:一文教您如何通过 Docker 快速搭建各种测试环境(Mysql, Redis, Elasticsearch, MongoDB) | 建议收藏 欢迎关注个人微信公众号: 小哈学Java, 文末分享阿里 P8 高级架构师吐血总结的 <Java 核心知识整理&面试.pdf>资源链接!! 个人网站: https://www.exception.site 小哈今天给大家分享的主题是,如何通过 Docker 快速搭建各种测试环境,本文列举的,也是小哈在工作中经常用到的,其中包括 Mysql

mysql数据库相关整理

数据库相关 1.InnoDB的日志 InnoDB有很多日志,日志中有2个概念需要分清楚,逻辑日志和物理日志. 1.1 逻辑日志有关操作的信息日志成为逻辑日志.比如,插入一条数据,undo逻辑日志的格式大致如下:<Ti,Qj,delete,U> Ti表示事务id,U表示Undo信息,Qj表示某次操作的唯一标示符 undo日志总是这样:1). insert操作,则记录一条delete逻辑日志. 2). delete操作,则记录一条insert逻辑日志.3). update操作,记录相反的updat

微软ASP.NET 电商网站开发实战 MVC6 +HTML5 +WCF+WebAPI+NoSQL+mongoDB+Redis+Core视频 代码 面试题

<微软ASP.NET 电商网站开发实战 MVC6 +HTML5 +WCF+WebAPI+NoSQL+mongoDB+Redis+Core 视频 代码 面试题 >下载网盘:https://yunpan.cn/cP7SNIjgJYYjA  访问密码 7fc6 微软特邀讲师 徐雷FrankXuLei 2016 授课 更新:.NET Core 1.0高并发框架+面试题更新:高性能缓存 Redis.NoSQL面试题 安装,增删改查 RedisHelper帮助类 购物车 会话服务器更新:REST WebA

nginx+play framework +mongoDB+redis +mysql+LBS实战总结

nginx+play framework +mongoDB+redis +mysql+LBS实战总结(一) 使用这个样的组合结构已经很久了,主要是实现web-server,不是做网站,二是纯粹的数据服务server.早就想总结一下,一直没有时间,最近也是一而再再而三的解决了使用途中的各种问题,从此片开始到之后悔慢慢的将这些经验教训总结下来,一边自己和朋友们借鉴使用.此片算是开篇吧,首先对这几种技术或者说平台做简单的介绍吧,顺便推荐一些文章给大家. nginx:本身是一个web server ,在

MySQL Innodb 事务实现过程相关内容的整理

MySQL事务的实现涉及到redo和undo以及purge,redo是保证事务的原子性和持久性:undo是保证事务的一致性(一致性读和多版本并发控制):purge清理undo表空间背景知识,对于Innodb表中的行每一行包括:6字节的事务ID(DB_TRX_ID)字段: 用来标识最近一次对本行记录做修改(INSERT|UPDATE)的事务的标识符, 即最后一次修改(INSERT|UPDATE)本行记录的事务id.7字节的回滚指针(DB_ROLL_PTR)字段: 指写入回滚段(ROLLBACK s

Java环境配置 数据库 缓存Redis Nosql MongoDB 安装

系统选择 centos 7.0 1.java安装篇 rpm -qa |grep java 检测是否java yum remove java-1.7.0-openjdk 使用命令删除java 到oracle官方下载java安装包 rpm -ivh jdk-7u60-linux-x64.rpm ->安装jdk 2.Tomcat 安装篇 在apache官方下载tomcat wget http://apache.fayea.com/apache-mirror/tomcat/tomcat-7/v7.0.5

HBase、Redis、MongoDB、Couchbase、LevelDB主流 NoSQL 数据库的对比

HBase.Redis.MongoDB.Couchbase.LevelDB主流 NoSQL 数据库的对比 最近小组准备启动一个 node 开源项目,从前端亲和力.大数据下的IO性能.可扩展性几点入手挑选了 NoSql 数据库,但具体使用哪一款产品还需要做一次选型. 我们最终把选项范围缩窄在 HBase.Redis.MongoDB.Couchbase.LevelDB 五款较主流的数据库产品中,本文将主要对它们进行分析对比. 鉴于缺乏项目中的实战经验沉淀,本文内容和观点主要还是从各平台资料搜罗汇总,

Python面试题整理-更新中

几个链接: 编程零基础应当如何开始学习 Python ? - 路人甲的回答 网易云课堂上有哪些值得推荐的 Python 教程? - 路人甲的回答 怎么用最短时间高效而踏实地学习 Python? - 路人甲的回答 如何学习Python爬虫[入门篇] - 学习编程 - 知乎专栏 Python常用库整理 - 学习编程 - 知乎专栏 学好Python的11个优秀资源 - 学习编程 - 知乎专栏 在开头依然推荐一个Python面试题整理比较好的网站:GitHub : 关于Python的面试题.同样推荐几道