精华内容
下载资源
问答
  • 实现 MongoDB 外键关联

    2019-09-20 14:36:22
    来源:...Mongodb 作为分布式文件存储的数据库,想实现多表关联 JOIN 查询并非易事。但通过集算器 SPL 语言,在 M...

    来源:http://stackoverflow.com/questions/29392169/populating-field-values-for-referred-documents-in-aggregate-call-in-mongoose  。

    【摘要】
            Mongodb 作为分布式文件存储的数据库,想实现多表关联 JOIN 查询并非易事。但通过集算器 SPL 语言,在 Mongodb 中多个表的外键关联查询,完全可以做到像关系数据库那样方便容易。若想了解更多,请前往乾学院:实现 MongoDB 外键关联!

            MongoDB 是一个分布式文件存储的数据库,也是 nosql 中最像关系型数据库的一种。但是 mongodb 采用文档模式设计的,这意味着集合中的文档可以有相同或不同的字段,因此在关系型数据库非常擅长的多表关联方面就显得差强人意。如果采用 Mongodb 本身的 API 则需要硬编码才能实现外键关联,不够直观且难度较大,这种情况下可以用集算器 SPL 语言来实现,下面用例子说明。

            Collection UserCourseProgress 记录着用户和课程的关系,其courseid字段是外键,指向Collection Course的_id字段。需要统计出每门课的人数,其中课程名称需要使用Course的title字段进行显示。

    UserCourseProgressCourse
    {"userId":"u01",
    "courseid":"c01",
    "timespent":6000,
    score:99}
    {"userId":"u02",
    "courseid":"c01",
    "timespent":6000,
    score:99}
    {"userId":"u03",
    "courseid":"c01",
    "timespent":6000,
    score:99}
    {"userId":"u04",
    "courseid":"c01",
    "timespent":6000,
    score:99}
    {"userId":"u05",
    "courseid":"c01",
    "timespent":6000,
    score:99}
    {"userId":"u01",
    "courseid":"c02",
    "timespent":6000,
    score:99}
    {"userId":"u02",
    "courseid":"c02",
    "timespent":6000,
    score:99}
    {"userId":"u03",
    "courseid":"c03",
    "timespent":6000,
    score:99}
    {"_id":"c01"
    "title":"Japanese159",
    "description":"Japanese   base",
    "category":"language"}
    {"_id":"c02"
    "title":"Chinese200",
    "description":"Chinese   middle",
    "category":"language"}
    {"_id":"c03"
    "title":"Political   science 280",
    "description":"Political   middle",
    "category":"politics"}
    {"_id":"c04"
    "title":"EE490",
    "description":"electronic   engineering hign",
    "category":"Electronic"}

            使用集算器SPL的代码如下:

     A
    1=mongo_open("mongodb://localhost:27017/local?user=test&password=test")
    2=mongo_shell(A1,"UserCourseProgress.aggregate([{$group:   {_id: {'primary':'$courseid'},'popularityCount': {$sum: 1}}}, {$sort:{'popularityCount':-1}},{$project:{_id:0,'courseid':'$_id.primary','popularityCount':1}}])")
    3=mongo_shell(A1,"Course.find(,{title:1})").fetch()
    4=A2.switch(courseid,A3:_id)
    5=A4.new(popularityCount,courseid.title)
    6=mongo_close(A1)

            A1: 连接MongoDB,连接字格式为mongo://ip:port/db?arg=value&…。

            A2: 统计出每门课的人数。这里使用MongoDB聚合函数aggregate在UserCourseProgress中取数,参数是遵循mongodb规范的汇总表达式。计算结果是内存数据,如下:

            

            A3: 用find函数从Course中取数,过滤条件为空。Find的结果是游标,由于课程数量较少,因此用可以fetch函数将游标读入内存,结果如下:

           Picture 4

             A4: 使用switch函数将A3中的外键切换为A2中的记录,结果如下:

            A5:按对象方式访问内存,形成新的二维表,结果如下:

            

            A6:关闭mongodb连接。

            通过上面的例子可以看到,借助集算器SPL语言,在Mongodb中多个表的外键关联查询,完全可以做到像关系数据库那样方便、容易、直观,不必担心因为Mongodb是非关系型数据库而带来的表间弱关联的影响。

    展开全文
  • 明了 | MongoDB 外键的基本使用

    千次阅读 2020-07-22 00:05:53
    小小继续进行学习,这次学习的内容是MongoDB外键的基本使用。 表示表关系的方法 在传统的关系型数据库当中,表示表关系,数据是通过索引来完善。 而在MongoDB中,表示表关系,使用的是嵌套,即,一个文档嵌套一个...

    小小继续进行学习,这次学习的内容是MongoDB外键的基本使用。

    表示表关系的方法

    在传统的关系型数据库当中,表示表关系,数据是通过索引来完善。
    而在MongoDB中,表示表关系,使用的是嵌套,即,一个文档嵌套一个文档的方法,作为MongoDB的两个文档的关联,以及使用,reference link作为文档和文档之间的关联。

    文档嵌套

    使用可视化的

    这里使用可视化的编辑器作为文档嵌套
    输入以下的文档对象

    {
        "ming": "ming",
    		"ming2": {
    			"ming3": "ming8"
    		}
    }
    

    插入成功以后如下

    这样就完成了文档的嵌套,即,表示两个文档之间的关联。

    使用JDK

    这里使用JDK进行连接。
    首先添加依赖

    <dependency>
        <groupId>org.mongodb</groupId>
        <artifactId>mongodb-driver</artifactId>
        <version>3.5.0</version>
    </dependency>
    

    进行连接

      try{   
           // 连接到 mongodb 服务
             MongoClient mongoClient = new MongoClient( "106.53.115.12" , 27017 );
           
             // 连接到数据库
             MongoDatabase mongoDatabase = mongoClient.getDatabase("koa");  
           System.out.println("Connect to database successfully");
            
          }catch(Exception e){
            System.err.println( e.getClass().getName() + ": " + e.getMessage() );
         }
    

    进行插入

    List<Document> collections = new ArrayList<Document>();
    Document d1 = new Document();
    d1.append("name", "三国演义").append("author", "罗贯中");
    Document d2 = new Document();
    d2.append("name", "红楼梦").append("author", d1);
    collections.add(d2);
    c.insertMany(collections);
    

    查询出来的数据如下

    {
    	"name" : "红楼梦",
    	"author": {
    		"name": "三国演义",
    		"author": "罗贯中"
    	}
    }
    

    此时就完成了文档的嵌套操作

    外键查询

    使用js语言,进行查询关联

    这里使用new DBRef的方式做外键查询。
    此时对于DBRef具有以下字段。

    $ref
    
             该$ref字段包含引用文档所在的集合的名称。
    
    $id
    
            该$id字段包含_id引用文档中字段的值。
    
    $db
    
          可选的。包含引用文档所在的数据库的名称。只有一些驱动程序支持$db引用,该字段说明可以跨集合关联
    

    这里对集合操作关联如下

    // 保存集合的数据
    > var a={value:"1"}  
     
    > var b={value:"2"}  
     
    > var c={value:"9"}  
     
    > var d={value:"10"}  
     
    > db.A.save(a)  
     
    > db.A.save(b)        
     
    > db.A.save(c)   
     
    > db.A.save(d)  
     // 进行集合数据的查询
    > db.A.find()                                                                                                 
     
    { "_id" : ObjectId("4e3f33ab6266b5845052c02b"), "value" : "1" }  
     
    { "_id" : ObjectId("4e3f33de6266b5845052c02c"), "value" : "2" }  
     
    { "_id" : ObjectId("4e3f33e06266b5845052c02d"), "value" : "9" }  
     
    { "_id" : ObjectId("4e3f33e26266b5845052c02e"), "value" : "10" }  
    

    进行集合关联,这里使用 new DBRef 方式完成集合的关联

    // 通过添加new DBRef 关键字,完成对集合的关联,这里通过new DBRef作为关键字,其中A为key,ObjectId 为value,进行关联
    > var Ba={Apid:[new DBRef('A',ObjectId("4e3f33de6266b5845052c02c"))],value:3}                        
     
     // 保存集合
    > db.B.save(Ba)  
     
    > var Ba={Apid:[new DBRef('A',ObjectId("4e3f33de6266b5845052c02c"))],value:4}  
     
    > db.B.insert(Ba)                                                              
     
    > var Ba={Apid:[new DBRef('A',ObjectId("4e3f33de6266b5845052c02c"))],value:7}  
     
    > db.B.insert(Ba)                                                              
     
    > var Ba={Apid:[new DBRef('A',ObjectId("4e3f33de6266b5845052c02c"))],value:8}  
     
    > db.B.insert(Ba)                                                              
     // 进行查询
    > db.B.find()  
     
     // 可以看到,已经成功关联
    { "_id" : ObjectId("4e3f3dd96266b5845052c035"), "Apid" : [ { "$ref" : "A", "$id" : ObjectId("4e3f33de6266b5845052c02c") } ], "value" : 3 }  
     
    { "_id" : ObjectId("4e3f3de16266b5845052c036"), "Apid" : [ { "$ref" : "A", "$id" : ObjectId("4e3f33de6266b5845052c02c") } ], "value" : 4 }  
     
    { "_id" : ObjectId("4e3f3dec6266b5845052c037"), "Apid" : [ { "$ref" : "A", "$id" : ObjectId("4e3f33de6266b5845052c02c") } ], "value" : 7 }  
     
    { "_id" : ObjectId("4e3f3df06266b5845052c038"), "Apid" : [ { "$ref" : "A", "$id" : ObjectId("4e3f33de6266b5845052c02c") } ], "value" : 8 } 
    

    使用mongo-java的方式操作

    	    	// 创建外键进行关联,其中外键为refB
    			// 其中选择对db数据库进行操作,选择id作为数据库的关联
    			DBRef refB = new DBRef(db,"transations", obj.get("_id"));
    			// 创建新的集合
    	    	DBObject subObj = new BasicDBObject();
    	    	// 外键插入
    			subObj.put("brand", refB);
    			// 进行保存
    	    	accounts.save(subObj);
    

    查询的结果如下

    可以看到其中$id 对应的值为其数据库mongodb的外键。
    这样就完成了对数据库的外键操作。

    公众号

    展开全文
  • MongoDB外键关联

    万次阅读 2015-12-15 10:54:41
    来源:... 用Mongodb本身的API需要硬编码才能实现外键关联,不够直观且难度较大,这种情况下可以用集算器来实现,下面用例子说明。  Collect
      来源:
    http://stackoverflow.com/questions/29392169/populating-field-values-for-referred-documents-in-aggregate-call-in-mongoose
    
    
      用Mongodb本身的API需要硬编码才能实现外键关联,不够直观且难度较大,这种情况下可以用集算器来实现,下面用例子说明。

      Collection UserCourseProgress记录着用户和课程的关系,其courseid字段是外键,指向Collection Course的_id字段。需要统计出每门课的人数,其中课程名称需要使用Course的title字段。


      集算器代码:


      A1:连接MongoDB,连接字格式为mongo://ip:port/db?arg=value&…

      A2:统计出每门课的人数。这里使用aggregate函数从MongoDB中取数,该函数继承自mongdb,第1个参数是collection名,第2个参数是汇总表达式,遵循mongodb规范。计算结果是内存数据,如下:


      A3: 从Course中取出码表。这里使用find函数从MongoDB中取数,该函数继承自mongdb,第2个参数是过滤条件,写法遵循mongodb规范。Find的结果是游标,由于课程数量较少,因此用fetch函数将游标读入内存,结果如下:


      A4:使用switch函数将A3中的外键切换为A2中的记录,结果如下:


      A5:按对象方式访问内存,形成新的二维表,结果如下:


      A6:关闭mongodb连接。


    展开全文
  • 如果向子表中插入一条记录,外键约束会让InnoDB检查对应的父表的记录,也就需要对父表对应记录进行加锁操作,来确保这条记录不会在这个事务完成之时就被删除了。这会导致额外的锁等待,甚至会导致一些死锁。 高...

    1.数据库语句

    1.1建表语句:

    CREATE TABLE IF NOT EXISTS `runoob_tbl`(
       `runoob_id` INT UNSIGNED AUTO_INCREMENT,
       `runoob_title` VARCHAR(100) NOT NULL,
       `runoob_author` VARCHAR(40) NOT NULL,
       `submission_date` DATE,
       PRIMARY KEY ( `runoob_id` )
    )ENGINE=InnoDB DEFAULT CHARSET=utf8;

    创建 MySql 的表时,表名和字段名外面的符号 ` 不是单引号,而是英文输入法状态下的反单引号,也就是键盘左上角 esc 按键下面的那一个 ~ 按键,坑惨了。

    反引号是为了区分 MySql 关键字与普通字符而引入的符号,一般的,表名与字段名都使用反引号。

    1.2修改语句:

    将 id 为 5 的手机号改为默认的 - : update students set tel=default where id=5;

    将所有人的年龄增加 1: update students set age=age+1;

    将手机号为 13288097888 的姓名改为 "小明", 年龄改为 19: update students setname="小明", age=19 where tel="13288097888";

    mysql alter命令

    添加列:

    ALTER TABLE tb_test01 add id_02 int(10) FIRST # 增加字段 id_02 并且放在第一个字段
    ALTER TABLE tb_test01 add id_03 int(10) AFTER id # 增加字段 id_03 并且放在id 后面

    • 删除

    ALTER TABLE tb_test01 drop id_03; #删除字段 id_03
    ALTER TABLE tb_test01 drop PRIMARY KEY; #删除主键,注: 如果表有主键,不删除主键,无论添加主键,还是在修改的时候增加主键设置,都会失败,需要先删除主键,才可以对主键进行操作

    • 修改:

    关键字:modify, change, rename, alter [field] set default [num]
    modify: 修改字段类型设置,不可以更改字段名
    change: 修改字段类型设置 可以更改字段名
    ALTER TABLE tb_test modify id_01 int(5) not null; # 把 id_01 字段类型修改 int(5),和非空
    ALTER TBALE tb_test change id_01 id_test int(10); 把 id_01 更名 id_test 并且字段类型设置为 INT(10)
    ALTER TABLE tb_test RENAME tb_test02; # 把表 tb_test 更名为 tb_test02;
    ALTER TABLE tb_test ALTER id_01 set default 1000; #把表tb_test 的字段 id_01 设置默认值为1000,其他的约束不变
    ALTER TABLE tb_test ALTER id_01 DROP DEFAULT; # 删除 字段 id_01 的默认设置值

    ALTER TABLE tb_test ENGINE = MYISAM; # 把 表tb_test 类型设置为 MYISAM; myqsl默认 INNODB

    1.3创建索引:

    --创建普通索引CREATE INDEX index_name ON table_name(col_name);

    --创建唯一索引CREATE UNIQUE INDEX index_name ON table_name(col_name);

    --创建普通组合索引CREATE INDEX index_name ON table_name(col_name_1,col_name_2);

    --创建唯一组合索引CREATE UNIQUE INDEX index_name ON table_name(col_name_1,col_name_2);

     通过修改表结构创建索引:ALTER TABLE table_name ADD INDEX index_name(col_name);

     创建表时直接指定索引

    1.4删除索引:

    --直接删除索引DROP INDEX index_name ON table_name;

    --修改表结构删除索引ALTER TABLE table_name DROP INDEX index_name;

    1.5查询语句:

     

    2视图

    2.1什么是视图?作用是什么?

    CREATE VIEW <视图名> AS <SELECT语句>

    视图兼有“表”和“查询”的特点,与查询类似的地方是,可以用来从一个或多个相关联的表中提取有用信息:与表相类似的地方是,可以用来更新其中的信息,并将更新结果永久地保存在磁盘上。可以从本地表(包括数据库表和自由表)、其他视图、存储在服务器上的表或远程数据源中创建视图来自百度文库数据库表和自由表的区别

    如果需要经常执行某项复杂查询,可以基于这个复杂查询建立视图,此后查询此视图即可,简化复杂查询;
    视图本质上就是一条SELECT语句,所以当访问视图时,只能访问到所对应的SELECT语句中涉及到的列,对基表中的其它列起到安全和保密的作用,可以限制数据访问。

    视图本身并不包含数据,只是基表数据的逻辑映射。当基表数据发生变化,视图数据也随之变化。所以当对视图执行DML操作时,实际上是对基表的DML操作。对视图执行DML操作的基本原则:
    •简单视图能够执行DML操作,下列情况除外:在基表中定义了非空列,但简单视图对应的SELECT语句并没有包含这个非空列,导致这个非空列对视图不可见,这时无法对视图执行INSERT操作;
    •如果视图定义中包含了函数、表达式、分组语句、DISTINCT关键字或ROWNUM伪列,不允许执行DML操作;
    •DML操作不能违反基表的约束条件。

    MySQL可以嵌套定义视图,即在一个视图上在定义另一个视图

    作用:

    对于一些关联表的复杂查询,使用视图有时候会大大简化问题,因此在许多场合下都可以看到视图的身影,

    首先视图可以简化应用上层的操作,让应用更专注于其所关心的数据。
    其次,视图能够对敏感数据提供安全保护,比如:对不同的用户定义不同的视图,可以使敏感数据不出现在不应该看到这些数据的用户视图上;
    也可以使用视图实现基于列的权限控制,而不需要真正的在数据库中创建列权限。
    再者,视图可以方便系统运维,比如:在重构schema的时候使用视图,使得在修改视图底层表结构的时候,应用代码还可以继续运行不报错。

    2.2视图能否加快查询速度

    MySQL底层通过两种算法来实现视图:临时表算法(TEMPTABLE)和合并算法(MERGE)。所谓临时表算法就是将SELECT语句的结果存放到临时表中,当需要访问视图的时候,直接访问这个临时表即可。而合并算法则是重写包含视图的查询,将视图定义的SQL直接包含进查询SQL中。

    可以在EXPLAN EXTENDED之后使用SHOW WARNINGS来查看使用视图的查询重写后的结果。如果采用临时表算法实现的视图,EXPLAIN中会显示为派生表(DERIVED),注意EXPLAIN时需要实际执行并产生临时表,所以有可能会很慢。临时表上没有任何索引,而且优化器也很难优化临时表上的查询。因此,如有可能,尽量使用合并算法会有更好的性能。

    一般来说,只要原表记录和视图中的记录无法建立一一映射的关系时,MySQL都将使用临时表算法来实现视图。比如创建视图的SQL中包含GROUP BYDISTINCTUNION、聚合函数、子查询的时候,视图都将采用临时表算法(这些规则在以后的版本中,可能会发生改变,具体请参考官方手册)。

    相比于其它关系型数据库的视图,MySQL的视图在功能上会弱很多,比如ORACLEMS SQL SERVER都支持物化视图。物化视图是指将视图结果数据存放在一个可以查询的表中,并定期从原始表中刷新数据到这张表中,这张表和普通物理表一样,可以创建索引、主键约束等等,性能相比于临时表会有质的提升。但遗憾的是MySQL目前并不支持物化视图,当然MySQL也不支持在视图中创建索引。

    3.存储过程、触发器、外键约束、用户自定义函数、PrepareStatement、字符集

    3.1存储过程、触发器

    不熟悉这两个东西的话,尽可能不要使用存储过程,存储过程非常不容易维护,也会增加使用成本,应该把业务逻辑放到客户端。

    存储过程:是一种在数据库中存储复杂程序,以便外部程序调用的一种数据库对象。

    存储过程是为了完成特定功能的SQL语句集,经编译创建并保存在数据库中,用户可通过指定存储过程的名字并给定参数(需要时)来调用执行。存储过程思想上很简单,就是数据库 SQL 语言层面的代码封装与重用。

    触发器可以让你在执行INSERTUPDATEDELETE时,执行一些特定的操作。在MySQL中可以选择在SQL执行之前触发还是在SQL执行后触发。一般用于实现一些强制的限制,这些限制如果在应用程序中实现会让业务代码变得非常复杂,而且它也可以减少客户端与服务器之间的通信。

    3.2外键约束

    目前在大多数互联网项目,特别是在大数据的场景下,已经不建议使用外键了,主要是考虑到外键的使用成本:

    • 外键通常要求每次修改数据时都要在另外一张表中执行一次查找操作。在InnoDB存储引擎中会强制外键使用索引,但在大数据的情况下,仍然不能忽略外键检查带来的开销,特别是当外键的选择性很低时,会导致一个非常大且选择性低的索引。
    • 如果向子表中插入一条记录,外键约束会让InnoDB检查对应的父表的记录,也就需要对父表对应记录进行加锁操作,来确保这条记录不会在这个事务完成之时就被删除了。这会导致额外的锁等待,甚至会导致一些死锁。
    • 高并发场景下,数据库很容易成为性能瓶颈,自然而然的就希望数据库可以水平扩展,这时就需要把数据的一致性控制放到应用层,也就是让应用服务器可以承担压力,这种情况下,数据库层面就不能使用外键。

    因此,当不用过多考虑数据库的性问题时,比如一些内部项目或传统行业项目(其使用人数有限,而且数据量一般不会太大),使用外键是一个不错的选择,毕竟想要确保相关表始终有一致的数据,使用外键要比在应用程序中检查一致性方便简单许多,此外,外键在相关数据的删除和更新操作上也会比在应用中要高效。

    3.3用户自定义函数

    存储过程只能使用SQL来编写,而UDF没有这个限制,可以使用支持C语言调用约定的任何编程语言来实现。

    3.4prepared statement

    SELECT order_no, order_amount FROM sales WHERE order_status = ? and buyer = ?

    为什么要使用绑定变量?总所周知的原因是可以预先编译,减少SQL注入的风险。

    当创建一个绑定变量SQL时,客户端向服务器发送了一个SQL语句原型,服务器收到这个SQL语句的框架后,解析并存储这个SQL语句的部分执行计划,返回给客户端一个SQL语句处理句柄,从此以后,客户端通过向服务器发送各个问号的取值和这个句柄来执行一个具体查询,这样就可以更高效地执行大量重复语句,因为:

    • 服务器只需要解析一次SQL语句
    • 服务器某些优化器的优化工作也只需要做一次,因为MySQL会缓存部分执行计划
    • 通信中仅仅发送的是参数,而不是整个语句,网络开销也会更小,而且以二进制发送参数和句柄要比发送ASCII文本的效率更高

    需要注意的是,MySQL并不是总能缓存执行计划,如果某些执行计划需要根据参入的参数来计算时,MySQL就无法缓存这部分执行计划。

    3种绑定变量类型之间的区别:

    1. 客户端模拟的绑定变量:客户端的驱动程序接收一个带参数的SQL,再将参数的值带入其中,最后将完整的查询发送到服务器。
    2. 服务器绑定变量:客户端使用特殊的二进制协议将带参数的SQL语句发送到服务器端,然后使用二进制协议将具体的参数值发送给服务器并执行。
    3. SQL接口的绑定变量:客户端先发送一个带参数的SQL语句到服务器端,这类似于使用prepared的SQL语句,然后发送设置的参数,最后在发送execute指令来执行SQL,所有这些都是用普通的文本传输协议。

    3.5字符集

    数据库字符集尽量使用UTF8,因为UTF8字符集是目前最适合于实现多种不同字符集之间的转换的字符集,可以最大程度上避免乱码问题,也可以方便以后的数据迁移。

    不要在一个数据库中使用多个不同的字符集,不同字符集之间的不兼容问题很难缠。

    MySQL采用“阶梯”式的方式来设定字符集默认值,每个数据库,每张表都有自己的默认值,它们逐层继承,最终最靠底层的默认设置将影响你创建的对象。比如,创建数据库时,将根据服务器上的character_set_server来设置数据库的默认字符集,同样的道理,根据database的字符集来指定库中所有表的字符集......不管是对数据库,还是表和列,只有当它们没有显式指定字符集时,默认字符集才会起作用。

    英文字符在UTF8字符集中只使用一个字节,而一个汉字则占用3个字节。

    4.索引

    索引用于快速找出在某个列中有一特定值的行。不使用索引,MySQL必须从第1条记录开始然后读完整个表直到找出相关的行,还需要考虑每次读入数据页的IO开销。而如果采取索引,则可以根据索引指向的页以及记录在页中的位置,迅速地读取目标页进而获取目标记录。

     

    4.1索引的种类

    1.

    1. 单列索引,即一个索引只包含单个列,一个表可以有多个单列索引。
    2. 组合索引,即一个索引包含多个列。

    mysql执行查询的时候,只能使用一个索引,mysql会选择一个最严格(获得结果集记录数最少)的索引。最左前缀:顾名思义,就是最左优先,打一比方

    alter table users add index lname_fname_age(lname,fname,age);
    创建了lname_fname_age多列索引,相当于创建了(lname)单列索引,(lname,fname)联合索引以及(lname,fname,age)联合索引。(节选自MySQL单列索引和组合索引(联合索引)的区别详解

    索引首先根据第一个字段来排列顺序,当名字相同时,则根据第三个字段,即出生日期来排序,正是因为这个原因,才有了索引的“最左原则”。

    2.Mysql目前主要有以下几种索引类型:

    1. 主键索引(PRIMAY KEY)它是一种特殊的唯一不允许有空值。为聚簇索引。
    2. 唯一索引(UNIQUE)它与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。
    3. 常规索引(INDEX)
    4. 全文索引(FULLTEXT)

    主键索引和非主键索引的区别是:非主键索引的叶子节点存放的是主键的值,而主键索引的叶子节点存放的是整行数据,其中非主键索引也被称为二级索引,而主键索引也被称为聚簇索引

    唯一性索引列允许空值,而主键列不允许为空值。主键列在创建时,已经默认为空值 + 唯一索引了。
    主键可以被其他表引用为外键,而唯一索引不能。
    一个表最多只能创建一个主键,但可以创建多个唯一索引。

    4.2索引底层为什么选用B+树

    在MySQL的存储引擎中,MyISAM不支持哈希索引,而InnoDB中的hash索引是存储引擎根据B-Tree索引自建的,后面会对其做具体说明。默认都未B+树。

    二叉查找树,AVL树,B树,B+树,红黑树

    二叉查找树,它是一种经典的数据结构,其左子树的值总是小于根的值,右子树的值总是大于根的值

    平衡二叉搜索树:首先需要符合二叉查找树的定义,其次必须满足任何节点的两个子树的高度差不能大于1。平衡二叉树的查找性能是比较高的(性能最好的是最优二叉树),查询性能越好,维护的成本就越大。

    随着数据库中数据的增加,索引本身大小随之增加,不可能全部存储在内存中,因此索引往往以索引文件的形式存储的磁盘上。这样的话,索引查找过程中就要产生磁盘I/O消耗,相对于内存存取,I/O存取的消耗要高几个数量级。可以想象一下一棵几百万节点的二叉树的深度是多少?如果将这么大深度的一颗二叉树放磁盘上,每读取一个节点,需要一次磁盘的I/O读取,整个查找的耗时显然是不能够接受的。

    减少查找过程中的I/O存取次数,一种行之有效的解决方法是减少树的深度,将二叉树变为m叉树(多路搜索树):B树每一层存放了更多的节点,由AVL树的“瘦高”变成了“矮胖”。可以相对减少磁盘IO的次数。MongoDB的索引就是用B树实现的。
    B树也是一种自平衡的树,在进行插入和删除操作时也需要对结点进行旋转等操作。不过,B树的查找不稳定,最好的情况就是在根节点查到了,最坏的情况就是在叶子结点查到。另外,B树在遍历方面比较麻烦,由于需要进行中序遍历,所以也会进行一定数量的磁盘IO。

    为了解决这些问题,出现了B+树B+Tree就是一种多路搜索树。理解B+Tree时,只需要理解其最重要的两个特征即可:第一,所有的关键字(可以理解为数据)都存储在叶子节点Leaf Page,非叶子节点(Index Page)并不存储真正的数据,所有记录节点都是按键值大小顺序存放在同一层叶子节点上。第二:所有的叶子节点由指针连接。如下图为高度为2的简化了的B+TreeB+Tree也提供了类似于平衡二叉树的旋转功能。当Leaf Page已满但其左右兄弟节点没有满的情况下,B+Tree并不急于去做拆分操作,而是将记录移到当前所在页的兄弟节点上。

    MySQL将每个节点的大小设置为一个页的整数倍,也就是在节点空间大小一定的情况下,每个节点可以存储更多的内结点,这样每个结点能索引的范围更大更精确。所有的叶子节点使用指针链接的好处是可以进行区间访问,比如上图中,如果查找大于20而小于30的记录,只需要找到节点20,就可以遍历指针依次找到25、30。如果没有链接指针的话,就无法进行区间查找。这也是MySQL使用B+Tree作为索引存储结构的重要原因。

    是计算机管理存储器的逻辑块,硬件及OS往往将主存和磁盘存储区分割为连续的大小相等的块,每个存储块称为一页(许多OS中,页的大小通常为4K)。主存和磁盘以页为单位交换数据。当程序要读取的数据不在主存中时,会触发一个缺页异常,此时系统会向磁盘发出读盘信号,磁盘会找到数据的起始位置并向后连续读取一页或几页载入内存中,然后一起返回,程序继续运行。

    磁盘本身存取就比主存慢很多,在加上机械运动损耗(特别是普通的机械硬盘),磁盘的存取速度往往是主存的几百万分之一,为了尽量减少磁盘I/O,磁盘往往不是严格按需读取,而是每次都会预读,即使只需要一个字节,磁盘也会从这个位置开始,顺序向后读取一定长度的数据放入内存,预读的长度一般为页的整数倍。

    MySQL巧妙利用了磁盘预读原理,将一个节点的大小设为等于一个页,这样每个节点只需要一次I/O就可以完全载入。为了达到这个目的,每次新建节点时,直接申请一个页的空间,这样就保证一个节点物理上也存储在一个页里,加之计算机存储分配都是按页对齐的,就实现了读取一个节点只需一次I/O。假设B+Tree的高度为h,一次检索最多需要h-1次I/O(根节点常驻内存),复杂度O(h) = O(logmN)。实际应用场景中,M通常较大,常常超过100,因此树的高度一般都比较小,通常不超过3。

    红黑树在查找方面和AVL树操作几乎相同。但是在插入和删除操作上,AVL树每次插入删除会进行大量的平衡度计算,红黑树是牺牲了严格的高度平衡的优越条件为代价,它只要求部分地达到平衡要求,结合变色,降低了对旋转的要求,从而提高了性能。红黑树能够以O(log2 n)的时间复杂度进行搜索、插入、删除操作。此外,由于它的设计,任何不平衡都会在三次旋转之内解决。

    红黑树广泛用于TreeMap、TreeSet,以及jdk1.8后的HashMap。

    虽然索引可以大大提高查询效率,但维护索引仍要花费很大的代价,因此合理的创建索引也就尤为重要。

    4.3聚簇索引

    聚簇索引并不是一种索引类型,只是一种存储方式。当表有了聚簇索引的时候,表的数据行都存放在索引树的叶子页中。无法把数据行放到两个不同的地方,所以一张表只允许有一个聚簇索引。
      索引使得大多数时候我们避免全表扫描,使数据的性能有一定的提高。而聚簇索引的影响力也是很大的。我们熟悉的Myisam和innodb两大引擎,innodb的默认数据结构是聚簇索引,而Myisam是非聚簇索引。
      Innodb是通过主键来聚集数据的,就是“被索引的列就是主键”。如果一张表没有主键,那就会通过某一唯一列来聚集数据,没有唯一列的时候,就会隐式的生成一个id,通过这个id来聚集数据。

     a):在Myisam引擎索引和数据是分开存储的,而Innodb是索引和数据是一起以idb文件的形式进行存储的。

      b):在访问速度上,聚簇索引比非聚簇索引快。非聚簇索引需要先查询一遍索引文件,得到索引,跟据索引获取数据。而聚簇索引的索引树的叶子节点的直接指向要查找的数据行。

     

    根据B+Tree的插入过程,取什么样的主键会带来什么问题?

      使用自增主键比其它主键好,因为根据B+Tree的插入,主键采用自增主键会保证每次都在最后面增加叶子节点。不会带来新数据的插入,导致前面的数据变动,而产生页分裂,随之带来空间碎片和时间的消耗。

    但是使用自增主键,这样的主键有上界啊,而且在并发的情况下怎么保证获取到的主键是正确的?怎么解决上界问题?

      对于并发怎么保证获取的主键是正确的,可以看innodb的Auto_increment锁机制。遇到这种问题则可能要考虑重新设计表,或者更改innodb_auotinc_lock_mode参数。

    4.4索引高性能策略

    1、MySQL不会使用索引的情况:非独立的列

    “独立的列”是指索引列不能是表达式的一部分,也不能是函数的参数。比如:

    select * from where id + 1 = 5

    2、前缀索引

    如果列很长,通常可以索引开始的部分字符,这样可以有效节约索引空间,从而提高索引效率。

    3多列索引和索引顺序

    在多数情况下,在多个列上建立独立的索引并不能提高查询性能。因为MySQL5.0之前就会随便选择一个列的索引,而新的版本会采用合并索引的策略。

    新版本做如下的优化:

    • 当出现多个索引做相交操作时(多个AND条件),通常来说一个包含所有相关列的索引要优于多个独立索引。
    • 当出现多个索引做联合操作时(多个OR条件),对结果集的合并、排序等操作需要耗费大量的CPU和内存资源,特别是当其中的某些索引的选择性不高,需要返回合并大量数据时,查询成本更高。所以这种情况下还不如走全表扫描。

    多列索引时,索引的顺序对于查询是至关重要的,很明显应该选择性更高的字段放到索引的前面,这样通过第一个字段就可以过滤掉大多数不符合条件的数据。

    索引选择性是指不重复的索引值和数据表的总记录数的比值,选择性越高查询效率越高,因为选择性越高的索引可以让MySQL在查询时过滤掉更多的行。唯一索引的选择性是1,这是最好的索引选择性,性能也是最好的。

    理解索引选择性的概念后,就不难确定哪个字段的选择性较高了,查一下就知道了,比如:

    SELECT * FROM payment where staff_id = 2 and customer_id = 584
    

    是应该创建(staff_id,customer_id)的索引还是应该颠倒一下顺序?执行下面的查询,哪个字段的选择性更接近1就把哪个字段索引前面就好。

    select count(distinct staff_id)/count(*) as staff_id_selectivity,
           count(distinct customer_id)/count(*) as customer_id_selectivity,
           count(*) from payment

    4.避免多个范围条件

    实际开发中,我们会经常使用多个范围条件,比如想查询某个时间段内登录过的用户:

    select user.* from user where login_time > '2017-04-01' and age between 18 and 30;
    

    这个查询有一个问题:它有两个范围条件,login_time列和age列,MySQL可以使用login_time列的索引或者age列的索引,但无法同时使用它们。

    5、覆盖索引

    如果一个索引包含或者说覆盖所有需要查询的字段的值,那么就没有必要再回表查询,这就称为覆盖索引。覆盖索引是非常有用的工具,可以极大的提高性能,因为查询只需要扫描索引会带来许多好处:

    • 索引条目远小于数据行大小,如果只读取索引,极大减少数据访问量
    • 索引是有按照列值顺序存储的,对于I/O密集型的范围查询要比随机从磁盘读取每一行数据的IO要少的多

    6、使用索引扫描来排序

    MySQL有两种方式可以生产有序的结果集,其一是对结果集进行排序的操作,其二是按照索引顺序扫描得出的结果自然是有序的。如果explain的结果中type列的值为index表示使用了索引扫描来做排序。

    扫描索引本身很快,因为只需要从一条索引记录移动到相邻的下一条记录。但如果索引本身不能覆盖所有需要查询的列,那么就不得不每扫描一条索引记录就回表查询一次对应的行。这个读取操作基本上是随机I/O,因此按照索引顺序读取数据的速度通常要比顺序地全表扫描要慢。

    在设计索引时,如果一个索引既能够满足排序,又满足查询,是最好的。

    只有当索引的列顺序ORDER BY子句的顺序完全一致,并且所有列的排序方向也一样时,才能够使用索引来对结果做排序。如果查询需要关联多张表,则只有ORDER BY子句引用的字段全部为第一张表时,才能使用索引做排序ORDER BY子句和查询的限制是一样的,都要满足最左前缀的要求(有一种情况例外,就是最左的列被指定为常数,下面是一个简单的示例),其他情况下都需要执行排序操作,而无法利用索引排序。

    // 最左列为常数,索引:(date,staff_id,customer_id)
    select  staff_id,customer_id from demo where date = '2015-06-01' order by staff_id,customer_id
    

    7、冗余和重复索引

    冗余索引是指在相同的列上按照相同的顺序创建的相同类型的索引,应当尽量避免这种索引,发现后立即删除。比如有一个索引(A,B),再创建索引(A)就是冗余索引。冗余索引经常发生在为表添加新索引时,比如有人新建了索引(A,B),但这个索引不是扩展已有的索引(A)

    大多数情况下都应该尽量扩展已有的索引而不是创建新索引。但有极少情况下出现性能方面的考虑需要冗余索引,比如扩展已有索引而导致其变得过大,从而影响到其他使用该索引的查询。

    8、删除长期未使用的索引

    定期删除一些长时间未使用过的索引是一个非常好的习惯。

    索引并不总是最好的工具,只有当索引帮助提高查询速度带来的好处大于其带来的额外工作时,索引才是有效的。对于非常小的表,简单的全表扫描更高效。对于中到大型的表,索引就非常有效。对于超大型的表,建立和维护索引的代价随之增长,这时候其他技术也许更有效,比如分区表。最后的最后,explain后再提测是一种美德

    9.其他索引失效的情况:

    使用索引需要注意:

    ⑴只对WHERE和ORDER BY需要查询的字段设置索引,避免无意义的硬盘开销;

    ⑵组合索引支持前缀索引;

    ⑶更新表的时候,如增删记录,MySQL会自动更新索引,保持树的平衡;因此更多的索引意味着更多的维护成本

    尽量减少like,但不是绝对不可用,”xxxx%” 是可以用到索引的,

    • 除了like,以下操作符也可用到索引:

    <,<=,=,>,>=,BETWEEN,IN

    <>,not in ,!=则不行

    哪些常见情况不能用索引?

    • like “%xxx”
    • not in , !=
    • 对列进行函数运算的情况(如 where md5(password) = “xxxx”)
    • WHERE index=1 OR A=10(or连接条件字段,全部设置索引的时候,才会使用索引,否则将不会使用索引。)
    • 存了数值的字符串类型字段(如手机号),查询时记得不要丢掉值的引号,否则无法用到该字段相关索引,反之则没关系

    也即select * from test where mobile = 13711112222;

    可是无法用到mobile字段的索引的哦(如果mobile是char 或 varchar类型的话)

    btw,千万不要尝试用int来存手机号(为什么?自己想!要不自己试试)手机号码11位数字超出了int的最大值

    4.5特定类型查询优化

    1.优化COUNT()查询

    它有两种不同的作用,其一是统计某个列值的数量,其二是统计行数。统计列值时,要求列值是非空的,它不会统计NULL。如果确认括号中的表达式不可能为空时,实际上就是在统计行数。最简单的就是当使用COUNT(*)时,并不是我们所想象的那样扩展成所有的列,实际上,它会忽略所有的列而直接统计行数。

    通常来说,执行COUNT()都需要扫描大量的行才能获取到精确的数据,因此很难优化,MySQL层面还能做得也就只有覆盖索引了。如果不还能解决问题,只有从架构层面解决了,比如添加汇总表,或者使用redis这样的外部缓存系统

    MySQL的统计总数count(*)与count(id)或count(字段)的之间的各自效率性能对比

    count(*)包括了所有的列,相当于行数,在统计结果的时候,不会忽略列值为NULL  
    count(1)包括了忽略所有列,用1代表代码行,在统计结果的时候,不会忽略列值为NULL  
    count(列名)只包括列名那一列,在统计结果的时候,会忽略列值为空(这里的空不是只空字符串或者0,而是表示null)的计数,即某个字段值为NULL时,不统计。

    因为count(*),自动会优化指定到那一个字段。所以没必要去count(1),用count(*),sql会帮你完成优化的 因此:count(1)和count(*)基本没有差别! 

    就是COUNT的时候,如果没有WHERE限制的话,MySQL直接返回保存有总的行数

    而在有WHERE限制的情况下,总是需要对MySQL进行全表遍历。

    注意:

     SELECT owner, COUNT(*) FROM pet;会报错需要加上groupby,因为有owner字段。

    sql中count(1)和count(*)有区别吗

    对于不加限定条件时

    对于 count(主键 id )来说,InnoDB 引擎会遍历整张表,把每一行的 id 值都取出来,返回给 server 层。server 层拿到 id 后,判断是不可能为空的,就按行累加。

    对于 count(1) 来说,InnoDB 引擎遍历整张表,但不取值。server 层对于返回的每一行,放一个数字“1” 进去,判断是不可能为空的,按行累加。单看这两个用法的差别的话,你能对比出来,count(1) 执行得要比 count(主键 id)快。因为从引擎 返回 id 会涉及到解析数据行,以及拷贝字段值的操作。对于 count(字段)来说:如果这个“字段”是定义为 not null 的话,一行行地从记录里面读出这个字段,判断不能为 null,按行累加;如果这个“字段”定义允许为 null,那么执行的时候,判断到有可能是 null,还要把值取出来再 判断一下,不是 null 才累加。

    而对于 count(*) 来说,并不会把全部字段取出来,而是专门做了优化,不取值,按行累加。所以排序效率:

    count(*)=count(1)>count(id)>count(字段)

    SQL中 select count(1) count中的1 到底是什么意思呢?和count(*)的区别

    count(1),其实就是计算一共有多少符合条件的行。
    1并不是表示第一个字段,而是表示一个固定值。
    其实就可以想成表中有这么一个字段,这个字段就是固定值1,count(1),就是计算一共有多少个1.
    同理,count(2),也可以,得到的值完全一样,count('x'),count('y')都是可以的。一样的理解方式。在你这个语句理都可以使用,返回的值完全是一样的。就是计数。
    count(*),执行时会把星号翻译成字段的具体名字,效果也是一样的,不过多了一个翻译的动作,比固定值的方式效率稍微低一些。

    2.优化关联查询

    在大数据场景下,表与表之间通过一个冗余字段来关联,要比直接使用JOIN有更好的性能。如果确实需要使用关联查询的情况下,需要特别注意的是:

    • 确保ONUSING字句中的列上有索引。在创建索引的时候就要考虑到关联的顺序。当表A和表B用列c关联的时候,如果优化器关联的顺序是A、B,那么就不需要在A表的对应列上创建索引。没有用到的索引会带来额外的负担,一般来说,除非有其他理由,只需要在关联顺序中的第二张表的相应列上创建索引(具体原因下文分析)。
    • 确保任何的GROUP BYORDER BY中的表达式只涉及到一个表中的列,这样MySQL才有可能使用索引来优化。

    要理解优化关联查询的第一个技巧,就需要理解MySQL是如何执行关联查询的。当前MySQL关联执行的策略非常简单,它对任何的关联都执行嵌套循环关联操作,即先在一个表中循环取出单条数据,然后在嵌套循环到下一个表中寻找匹配的行,依次下去,直到找到所有表中匹配的行为为止。然后根据各个表匹配的行,返回查询中需要的各个列。

    太抽象了?以上面的示例来说明,比如有这样的一个查询:

    SELECT A.xx,B.yy 
    FROM A INNER JOIN B USING(c)
    WHERE A.xx IN (5,6)
    

    假设MySQL按照查询中的关联顺序A、B来进行关联操作,那么可以用下面的伪代码表示MySQL如何完成这个查询:

    outer_iterator = SELECT A.xx,A.c FROM A WHERE A.xx IN (5,6);
    outer_row = outer_iterator.next;
    while(outer_row) {
        inner_iterator = SELECT B.yy FROM B WHERE B.c = outer_row.c;
        inner_row = inner_iterator.next;
        while(inner_row) {
            output[inner_row.yy,outer_row.xx];
            inner_row = inner_iterator.next;
        }
        outer_row = outer_iterator.next;
    }
    

    可以看到,最外层的查询是根据A.xx列来查询的,A.c上如果有索引的话,整个关联查询也不会使用。再看内层的查询,很明显B.c上如果有索引的话,能够加速查询,因此只需要在关联顺序中的第二张表的相应列上创建索引即可。

    3.优化LIMIT分页

    当需要分页操作时,通常会使用LIMIT加上偏移量的办法实现,同时加上合适的ORDER BY字句。如果有对应的索引,通常效率会不错,否则,MySQL需要做大量的文件排序操作。

    一个常见的问题是当偏移量非常大的时候,比如:LIMIT 10000 20这样的查询,MySQL需要查询10020条记录然后只返回20条记录,前面的10000条都将被抛弃,这样的代价非常高。

    优化这种查询一个最简单的办法就是尽可能的使用覆盖索引扫描,而不是查询所有的列。然后根据需要做一次关联查询再返回所有的列。对于偏移量很大时,这样做的效率会提升非常大。考虑下面的查询:

    SELECT film_id,description FROM film ORDER BY title LIMIT 50,5;
    

    如果这张表非常大,那么这个查询最好改成下面的样子:

    SELECT film.film_id,film.description
    FROM film INNER JOIN (
        SELECT film_id FROM film ORDER BY title LIMIT 50,5
    ) AS tmp USING(film_id);
    

    用using关键字进行简化链接查询1.查询必须是等值连接。2.等值连接中的列必须具有相同的名称和数据类型。)

    这里的延迟关联将大大提升查询效率,让MySQL扫描尽可能少的页面,获取需要访问的记录后在根据关联列回原表查询所需要的列。

    有时候如果可以使用书签记录上次取数据的位置,那么下次就可以直接从该书签记录的位置开始扫描,这样就可以避免使用OFFSET,比如下面的查询:

    SELECT id FROM t LIMIT 10000, 10;
    改为:
    SELECT id FROM t WHERE id > 10000 LIMIT 10;
    

    其他优化的办法还包括使用预先计算的汇总表,或者关联到一个冗余表,冗余表中只包含主键列和需要做排序的列

    4.优化UNION

    MySQL处理UNION的策略是先创建临时表,然后再把各个查询结果插入到临时表中,最后再来做查询。因此很多优化策略在UNION查询中都没有办法很好的时候。经常需要手动将WHERELIMITORDER BY等字句“下推”到各个子查询中,以便优化器可以充分利用这些条件先优化。

    除非确实需要服务器去重,否则就一定要使用UNION ALL,如果没有ALL关键字,MySQL会给临时表加上DISTINCT选项,这会导致整个临时表的数据做唯一性检查,这样做的代价非常高。当然即使使用ALL关键字,MySQL总是将结果放入临时表,然后再读出,再返回给客户端。虽然很多时候没有这个必要,比如有时候可以直接把每个子查询的结果返回给客户端。

    展开全文
  • MongoDB

    2019-02-19 12:22:00
    1.定义 MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。... 它和我们使用的关系型数据库最大的区别就是约束性,可以说文件型数据库几乎不存在约束性,理论上没有主外键约束,没有存储的数据类型...
  • mongodb学习总结

    2019-05-31 12:18:42
    表结构对比 MongoDB Mysql 表 collections tables 行 documents ...主键约束,外键约束   mysql MongoDB 进去库 use dbname use dbname 显示表列表 show tables show collections ...
  • 了解MongoDB

    2019-01-16 22:13:00
    -MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。...-它和我们使用的关系型数据库最大的区别就是约束性,可以说文件型数据库几乎不存在约束性,理论上没有主外键约束,没有存储的数据类型约束等等 ...
  • MongoDB操作详解

    2018-09-17 15:49:01
    MongoDB和我们使用的关系型数据库最大的区别就是约束性,可以说文件型数据库几乎不存在约束性,理论上没有主外键约束,没有存储的数据类型约束等 关系型数据库中有一个“表”的概念,有“字段”的概念呢,有“行...
  • MongoDB基础操作

    2019-09-25 09:32:12
    开启数据库服务 MongoDB 是一个基于分布式文件存储的数据库。...它和关系型数据库最大的区别就是约束性,可以说文件型数据库几乎不存在约束性,理论上没有主外键约束,没有存储的数据类型约束等等...
  • MongoDB是什么

    2020-12-09 14:59:13
    MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。...它和我们使用的关系型数据库最大的区别就是约束性,可以说文件型数据库几乎不存在约束性,理论上没有主外键约束,没有存储的数据类型约束等等
  • mongodb

    千次阅读 2014-03-09 12:08:44
    MongoDB的内部构造《MongoDB The Definitive Guide》 MongoDB的官方文档基本是how to do的介绍,而关于how it worked却少之又少,本人也刚买了《MongoDB TheDefinitive Guide》的影印版,还没来得
  • Mongodb之简介

    2019-01-16 15:10:00
    MongoDB是一个基于分布式存储的...它和我们使用的关系型数据库最大的区别就是约束性,可以说文件型数据库几乎不存在约束性,理论上没有主外键约束,没有存储的数据类型约束等等 关系型数据库中有一个 "表" 的概念,有...
  • mongoDB的基本用法

    2019-01-16 15:41:00
    一.MongoDB初识 什么是MongoDB MongoDB是一个基于分布式文件存储的数据库....它和我们使用的关系型数据库最大的区别就是约束性,可以说文件数据库基本不存在约束性,理论上没有外键约束,没有存储数据...
  • MongoDB文件型数据库

    2019-09-25 21:24:43
    初始MongoDB MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。...它和我们使用的关系型数据库最大的区别就是约束性,可以说文件型数据库几乎不存在约束性,理论上没有主外键约束,没有存储的数...
  • MongoDB介绍

    千次阅读 2019-05-31 21:16:15
    最近在回顾mongodb的相关知识,输出一篇文章做为MongoDB知识点的总结。 总结的目的在于回顾MongoDB的相关知识点,明确MongoDB在企业级应用中充当的角色,为之后的技术选型提供一个可查阅的信息简报 一、概述 1....
  • mongoDB操作详细

    2018-08-23 15:34:00
    它和我们使用的关系型数据库最大的区别就是约束性,可以说文件型数据库几乎不存在约束性,理论上没有主外键约束,没有存储的数据类型约束等等 关系型数据库中有一个 "表" 的概念,有 "字段" 的概念,有 "数据条目" 的...
  • MongoDBMongoDB操作及python中使用MongoDB 一、Mongodb简介 二、MongoDB的增删改查 三、MongoDB的数据类型 四、MongoDB的关键字及修改器 五、python下使用MongoDB(pyMongo) 一、Mongodb简介 了解...
  • 1 MongoDB 的简介  MongoDB 是由C++编写的NOSQL 非关系型数据库,是非关系型数据库中最像关系型数据库的NoSQL 数据库。 2 MongoDB 和 关系型数据库对比  MongoDB 中的 Collection (集合) 对应 关系型数据库中的...
  • MongoDB总结

    千次阅读 2017-09-08 14:53:55
    MongoDB的官方文档基本是how to do的介绍,而关于how it worked却少之又少,本人也刚买了《MongoDB TheDefinitive Guide》的影印版,还没来得及看,本文原作者将其书中一些关于MongoDB内部现实方面的一些知识介绍...
  • MongoDB的安装以及启动

    2019-09-22 17:43:08
    1.首先什么是MongoDBMongoDB是一个基于分布式文件存储的数据库,是由...它和我们使用的关系型数据库最大的区别就是约束性,可以说文件型数据库几乎不存在约束性,理论上没有主外键约束,没有存储的数据类型约束等...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,171
精华内容 1,268
关键字:

mongodb外键约束