Skip to content

1.4 MongoDB vs 关系型数据库

1. 概述

MongoDB作为文档型数据库的代表,与传统的关系型数据库(如MySQL、PostgreSQL)在数据模型、查询方式、扩展性等方面存在显著差异。理解这些差异对于选择合适的数据库技术至关重要。本章节将详细对比MongoDB和关系型数据库的特点、优缺点以及适用场景。

2. 基本概念

2.1 数据模型对比

关系型数据库使用表、行、列的结构化数据模型,数据必须预先定义模式(Schema),表之间通过外键建立关系。

MongoDB使用集合、文档、字段的文档型数据模型,数据模式灵活,可以动态变化,文档之间通过引用建立关系。

语法:关系型数据库使用SQL语言,MongoDB使用BSON格式和查询语言

语义:数据模型决定了数据的组织方式和查询效率

规范

  • 关系型数据库需要预先定义表结构
  • MongoDB不需要预先定义文档结构
  • 两者都需要设计合理的数据模型

2.2 查询语言对比

关系型数据库使用SQL(结构化查询语言),是一种声明式语言,用户描述想要什么数据,而不是如何获取数据。

MongoDB使用MongoDB查询语言(MQL),是一种类JSON的查询语言,支持丰富的查询操作符和聚合管道。

语法:SQL使用SELECT、FROM、WHERE等关键字,MQL使用find、aggregate等方法

语义:查询语言决定了数据检索的复杂度和灵活性

规范

  • SQL适合复杂的多表关联查询
  • MQL适合灵活的文档查询和聚合

2.3 事务处理对比

关系型数据库支持ACID事务,确保数据的一致性和完整性,适合处理复杂的业务逻辑。

MongoDB在早期版本不支持多文档事务,从4.0版本开始支持副本集事务,4.2版本支持分片集群事务。

语法:关系型数据库使用BEGIN、COMMIT、ROLLBACK,MongoDB使用startSession、commitTransaction

语义:事务处理决定了数据的一致性保证

规范

  • 关系型数据库的事务处理更加成熟
  • MongoDB的事务功能正在不断完善

3. 原理深度解析

3.1 存储引擎对比

关系型数据库通常使用B+树索引结构,数据按行存储,支持复杂的查询优化和执行计划。

MongoDB使用BSON格式存储数据,支持多种存储引擎(如WiredTiger、In-Memory),文档级别的并发控制。

3.2 扩展性对比

关系型数据库主要支持垂直扩展(增加硬件资源),水平扩展需要复杂的分库分表方案。

MongoDB原生支持水平扩展,通过分片技术可以轻松添加服务器来扩展存储容量和吞吐量。

3.3 数据一致性对比

关系型数据库强调强一致性,使用ACID特性确保数据的一致性。

MongoDB提供可调的一致性级别,可以根据业务需求在一致性和性能之间进行权衡。

4. 常见错误与踩坑点

4.1 错误1:将MongoDB当作关系型数据库使用

错误表现:在MongoDB中设计过多的关联查询,性能低下

产生原因:没有理解MongoDB的数据模型特点,仍然使用关系型数据库的思维

解决方案:根据MongoDB的特点设计数据模型,合理使用内嵌和引用

php
<?php
require 'vendor/autoload.php';

$client = new MongoDB\Client("mongodb://localhost:27017");

$usersCollection = $client->test->users;
$ordersCollection = $client->test->orders;

$usersCollection->insertOne([
    'user_id' => 'user_001',
    'name' => '张三',
    'email' => 'zhangsan@example.com'
]);

$ordersCollection->insertOne([
    'order_id' => 'ORD_001',
    'user_id' => 'user_001',
    'total' => 1000.00
]);

echo "错误做法:使用关联查询\n";
$user = $usersCollection->findOne(['user_id' => 'user_001']);
$orders = $ordersCollection->find(['user_id' => 'user_001'])->toArray();
echo "用户: " . $user['name'] . ", 订单数: " . count($orders) . "\n";

echo "\n正确做法:使用内嵌文档\n";
$optimizedCollection = $client->test->optimized_users;
$optimizedCollection->insertOne([
    'user_id' => 'user_002',
    'name' => '李四',
    'email' => 'lisi@example.com',
    'orders' => [
        ['order_id' => 'ORD_002', 'total' => 2000.00],
        ['order_id' => 'ORD_003', 'total' => 3000.00]
    ]
]);

$optimizedUser = $optimizedCollection->findOne(['user_id' => 'user_002']);
echo "用户: " . $optimizedUser['name'] . ", 订单数: " . count($optimizedUser['orders']) . "\n";

echo "运行结果: 演示数据模型设计差异\n";
?>

运行结果

错误做法:使用关联查询
用户: 张三, 订单数: 1

正确做法:使用内嵌文档
用户: 李四, 订单数: 2
运行结果: 演示数据模型设计差异

4.2 错误2:忽视MongoDB的事务限制

错误表现:在MongoDB中执行复杂的多文档事务,性能严重下降

产生原因:没有了解MongoDB事务的性能特点和限制

解决方案:合理使用事务,避免在事务中执行大量操作

php
<?php
require 'vendor/autoload.php';

$client = new MongoDB\Client("mongodb://localhost:27017");

$session = $client->startSession();

try {
    $session->startTransaction([
        'readConcern' => new MongoDB\Driver\ReadConcern('snapshot'),
        'writeConcern' => new MongoDB\Driver\WriteConcern(MongoDB\Driver\WriteConcern::MAJORITY)
    ]);

    $collection = $client->test->transactions;
    
    $collection->insertOne(
        ['name' => '文档1', 'value' => 100],
        ['session' => $session]
    );
    
    $collection->insertOne(
        ['name' => '文档2', 'value' => 200],
        ['session' => $session]
    );
    
    $collection->updateOne(
        ['name' => '文档1'],
        ['$inc' => ['value' => 50]],
        ['session' => $session]
    );

    $session->commitTransaction();
    echo "事务提交成功\n";
} catch (Exception $e) {
    $session->abortTransaction();
    echo "事务回滚: " . $e->getMessage() . "\n";
}

echo "警告:MongoDB事务性能低于关系型数据库\n";
echo "建议:只在必要时使用事务,尽量减少事务中的操作\n";

echo "运行结果: 演示事务使用\n";
?>

运行结果

事务提交成功
警告:MongoDB事务性能低于关系型数据库
建议:只在必要时使用事务,尽量减少事务中的操作
运行结果: 演示事务使用

4.3 错误3:忽略索引的重要性

错误表现:在MongoDB中执行查询时没有创建索引,性能极差

产生原因:认为MongoDB会自动优化查询,忽略了索引的作用

解决方案:根据查询模式创建合适的索引

php
<?php
require 'vendor/autoload.php';

$client = new MongoDB\Client("mongodb://localhost:27017");
$collection = $client->test->index_test;

for ($i = 0; $i < 10000; $i++) {
    $collection->insertOne([
        'name' => '用户' . $i,
        'email' => 'user' . $i . '@example.com',
        'age' => rand(18, 60),
        'created_at' => new MongoDB\BSON\UTCDateTime()
    ]);
}

echo "插入10000条文档\n";

$startTime = microtime(true);
$result = $collection->findOne(['email' => 'user5000@example.com']);
$noIndexTime = microtime(true) - $startTime;
echo "无索引查询耗时: " . round($noIndexTime, 4) . "秒\n";

$collection->createIndex(['email' => 1]);

$startTime = microtime(true);
$result = $collection->findOne(['email' => 'user5000@example.com']);
$withIndexTime = microtime(true) - $startTime;
echo "有索引查询耗时: " . round($withIndexTime, 4) . "秒\n";

echo "性能提升: " . round(($noIndexTime - $withIndexTime) / $noIndexTime * 100, 2) . "%\n";

echo "运行结果: 演示索引重要性\n";
?>

运行结果

插入10000条文档
无索引查询耗时: 0.0234秒
有索引查询耗时: 0.0008秒
性能提升: 96.58%
运行结果: 演示索引重要性

5. 常见应用场景

5.1 内容管理系统

场景描述:存储和管理网站的各种内容

关系型数据库方案:使用多个表存储内容、分类、标签等,通过外键关联

MongoDB方案:使用文档存储灵活的内容结构,支持动态字段

php
<?php
require 'vendor/autoload.php';

$client = new MongoDB\Client("mongodb://localhost:27017");
$collection = $client->cms->articles;

$article = [
    'title' => 'MongoDB入门教程',
    'slug' => 'mongodb-tutorial',
    'content' => 'MongoDB是一个强大的文档型数据库...',
    'excerpt' => '本文介绍MongoDB的基础知识...',
    'author' => [
        'user_id' => 'user_001',
        'name' => '技术博主',
        'avatar' => 'avatar.jpg'
    ],
    'category' => '技术',
    'tags' => ['MongoDB', '数据库', '教程'],
    'featured_image' => 'featured.jpg',
    'metadata' => [
        'views' => 0,
        'likes' => [],
        'comments_count' => 0,
        'shares' => 0
    ],
    'seo' => [
        'meta_title' => 'MongoDB入门教程',
        'meta_description' => '本文介绍MongoDB的基础知识...',
        'keywords' => 'MongoDB, 数据库, 教程'
    ],
    'status' => 'published',
    'published_at' => new MongoDB\BSON\UTCDateTime(),
    'created_at' => new MongoDB\BSON\UTCDateTime(),
    'updated_at' => new MongoDB\BSON\UTCDateTime()
];

$result = $collection->insertOne($article);
echo "插入文章ID: " . $result->getInsertedId() . "\n";

$retrieved = $collection->findOne(['slug' => 'mongodb-tutorial']);
echo "标题: " . $retrieved['title'] . "\n";
echo "作者: " . $retrieved['author']['name'] . "\n";
echo "标签: " . implode(', ', $retrieved['tags']) . "\n";

echo "运行结果: MongoDB内容管理系统演示\n";
?>

运行结果

插入文章ID: 65abc123def4567890123489
标题: MongoDB入门教程
作者: 技术博主
标签: MongoDB, 数据库, 教程
运行结果: MongoDB内容管理系统演示

5.2 电商系统

场景描述:存储商品信息、订单、用户数据等

关系型数据库方案:使用商品表、订单表、订单详情表等多个表

MongoDB方案:使用文档存储商品和订单,支持灵活的规格和属性

php
<?php
require 'vendor/autoload.php';

$client = new MongoDB\Client("mongodb://localhost:27017");
$collection = $client->ecommerce->products;

$product = [
    'product_id' => 'PROD_001',
    'name' => '智能手机',
    'description' => '高性能智能手机',
    'category' => '电子产品',
    'brand' => '小米',
    'variants' => [
        [
            'sku' => 'SKU_001_BLACK',
            'color' => '黑色',
            'price' => 2999.00,
            'stock' => 50,
            'specifications' => [
                'storage' => '256GB',
                'ram' => '8GB'
            ]
        ],
        [
            'sku' => 'SKU_001_WHITE',
            'color' => '白色',
            'price' => 2999.00,
            'stock' => 30,
            'specifications' => [
                'storage' => '256GB',
                'ram' => '8GB'
            ]
        ]
    ],
    'images' => ['phone1.jpg', 'phone2.jpg'],
    'attributes' => [
        'screen_size' => '6.67英寸',
        'battery' => '5000mAh',
        'processor' => 'Snapdragon 8 Gen 3'
    ],
    'reviews' => [
        [
            'user_id' => 'user_001',
            'user_name' => '张三',
            'rating' => 5,
            'comment' => '手机很好用!',
            'created_at' => new MongoDB\BSON\UTCDateTime()
        ]
    ],
    'stats' => [
        'average_rating' => 5.0,
        'total_reviews' => 1,
        'total_sales' => 0
    ],
    'created_at' => new MongoDB\BSON\UTCDateTime(),
    'updated_at' => new MongoDB\BSON\UTCDateTime()
];

$result = $collection->insertOne($product);
echo "插入产品ID: " . $result->getInsertedId() . "\n";

$retrieved = $collection->findOne(['product_id' => 'PROD_001']);
echo "产品名称: " . $retrieved['name'] . "\n";
echo "变体数量: " . count($retrieved['variants']) . "\n";
echo "平均评分: " . $retrieved['stats']['average_rating'] . "\n";

echo "运行结果: MongoDB电商系统演示\n";
?>

运行结果

插入产品ID: 65abc123def4567890123490
产品名称: 智能手机
变体数量: 2
平均评分: 5
运行结果: MongoDB电商系统演示

5.3 日志系统

场景描述:存储和分析应用程序日志

关系型数据库方案:使用日志表,需要预先定义字段,扩展性差

MongoDB方案:使用时间序列集合,支持灵活的日志结构和高效查询

php
<?php
require 'vendor/autoload.php';

$client = new MongoDB\Client("mongodb://localhost:27017");
$database = $client->logs;

try {
    $database->createCollection('application_logs', [
        'timeseries' => [
            'timeField' => 'timestamp',
            'metaField' => 'metadata',
            'granularity' => 'seconds'
        ]
    ]);
    echo "创建时间序列集合成功\n";
} catch (Exception $e) {
    echo "集合已存在\n";
}

$collection = $database->application_logs;

$logEntry = [
    'timestamp' => new MongoDB\BSON\UTCDateTime(),
    'level' => 'INFO',
    'message' => '用户登录成功',
    'metadata' => [
        'service' => 'auth-service',
        'user_id' => 'user_001',
        'ip_address' => '192.168.1.100',
        'request_id' => 'req_123456',
        'environment' => 'production'
    ],
    'context' => [
        'duration' => 0.023,
        'user_agent' => 'Mozilla/5.0...',
        'referrer' => 'https://example.com'
    ]
];

$result = $collection->insertOne($logEntry);
echo "插入日志ID: " . $result->getInsertedId() . "\n";

$logs = $collection->find([
    'timestamp' => [
        '$gte' => new MongoDB\BSON\UTCDateTime(strtotime('-1 hour') * 1000)
    ],
    'level' => 'INFO'
], [
    'sort' => ['timestamp' => -1],
    'limit' => 10
]);

echo "\n最近1小时的INFO日志:\n";
foreach ($logs as $log) {
    $time = $log['timestamp']->toDateTime()->format('Y-m-d H:i:s');
    echo "[{$time}] " . $log['level'] . ": " . $log['message'] . "\n";
}

echo "运行结果: MongoDB日志系统演示\n";
?>

运行结果

创建时间序列集合成功
插入日志ID: 65abc123def4567890123491

最近1小时的INFO日志:
[2024-03-08 10:30:00] INFO: 用户登录成功
运行结果: MongoDB日志系统演示

5.4 社交平台

场景描述:存储用户信息、帖子、关系等

关系型数据库方案:使用用户表、帖子表、关注表、点赞表等多个表

MongoDB方案:使用文档存储用户和帖子,使用数组存储关系

php
<?php
require 'vendor/autoload.php';

$client = new MongoDB\Client("mongodb://localhost:27017");

$usersCollection = $client->social->users;
$postsCollection = $client->social->posts;

$user = [
    'user_id' => 'user_001',
    'username' => 'alice',
    'profile' => [
        'name' => 'Alice',
        'avatar' => 'avatar.jpg',
        'bio' => '热爱生活'
    ],
    'following' => [],
    'followers' => [],
    'stats' => [
        'posts_count' => 0,
        'following_count' => 0,
        'followers_count' => 0
    ],
    'created_at' => new MongoDB\BSON\UTCDateTime()
];

$usersCollection->insertOne($user);
echo "创建用户\n";

$post = [
    'post_id' => 'post_001',
    'user_id' => 'user_001',
    'user_name' => 'Alice',
    'user_avatar' => 'avatar.jpg',
    'content' => [
        'text' => '今天天气真好!',
        'images' => ['photo1.jpg']
    ],
    'type' => 'photo',
    'metadata' => [
        'likes_count' => 0,
        'comments_count' => 0,
        'shares_count' => 0
    ],
    'created_at' => new MongoDB\BSON\UTCDateTime()
];

$postsCollection->insertOne($post);
echo "创建帖子\n";

$usersCollection->updateOne(
    ['user_id' => 'user_001'],
    ['$inc' => ['stats.posts_count' => 1]]
);

echo "更新用户统计\n";

$retrievedUser = $usersCollection->findOne(['user_id' => 'user_001']);
echo "用户: " . $retrievedUser['profile']['name'] . "\n";
echo "帖子数: " . $retrievedUser['stats']['posts_count'] . "\n";

echo "运行结果: MongoDB社交平台演示\n";
?>

运行结果

创建用户
创建帖子
更新用户统计
用户: Alice
帖子数: 1
运行结果: MongoDB社交平台演示

5.5 物联网数据

场景描述:存储传感器数据、设备状态等时序数据

关系型数据库方案:使用传感器数据表,需要预先定义字段,扩展性差

MongoDB方案:使用时间序列集合,支持高效的时序数据存储和查询

php
<?php
require 'vendor/autoload.php';

$client = new MongoDB\Client("mongodb://localhost:27017");
$database = $client->iot;

try {
    $database->createCollection('sensor_data', [
        'timeseries' => [
            'timeField' => 'timestamp',
            'metaField' => 'metadata',
            'granularity' => 'seconds'
        ]
    ]);
    echo "创建时间序列集合成功\n";
} catch (Exception $e) {
    echo "集合已存在\n";
}

$collection = $database->sensor_data;

$sensorData = [
    'timestamp' => new MongoDB\BSON\UTCDateTime(),
    'temperature' => 23.5,
    'humidity' => 65.2,
    'pressure' => 1013.25,
    'metadata' => [
        'device_id' => 'sensor_001',
        'location' => '北京',
        'device_type' => 'temperature_sensor'
    ],
    'status' => 'normal',
    'battery_level' => 85
];

$result = $collection->insertOne($sensorData);
echo "插入传感器数据ID: " . $result->getInsertedId() . "\n";

$stats = $collection->aggregate([
    [
        '$match' => [
            'metadata.device_id' => 'sensor_001',
            'timestamp' => [
                '$gte' => new MongoDB\BSON\UTCDateTime(strtotime('-24 hours') * 1000)
            ]
        ]
    ],
    [
        '$group' => [
            '_id' => '$metadata.device_id',
            'avg_temperature' => ['$avg' => '$temperature'],
            'avg_humidity' => ['$avg' => '$humidity'],
            'count' => ['$sum' => 1]
        ]
    ]
]);

echo "\n传感器统计数据:\n";
foreach ($stats as $stat) {
    echo "设备: " . $stat['_id'] . "\n";
    echo "平均温度: " . round($stat['avg_temperature'], 2) . "°C\n";
    echo "平均湿度: " . round($stat['avg_humidity'], 2) . "%\n";
    echo "数据点数: " . $stat['count'] . "\n";
}

echo "运行结果: MongoDB物联网数据演示\n";
?>

运行结果

创建时间序列集合成功
插入传感器数据ID: 65abc123def4567890123492

传感器统计数据:
设备: sensor_001
平均温度: 23.5°C
平均湿度: 65.2%
数据点数: 1
运行结果: MongoDB物联网数据演示

6. 企业级进阶应用场景

6.1 实时分析系统

场景描述:实时处理和分析大量数据,提供实时报表和仪表板

关系型数据库方案:使用复杂的SQL查询和存储过程,性能受限

MongoDB方案:使用聚合管道和Change Streams实现实时分析

php
<?php
require 'vendor/autoload.php';

$client = new MongoDB\Client("mongodb://localhost:27017");
$collection = $client->analytics->events;

$event = [
    'event_type' => 'page_view',
    'user_id' => 'user_001',
    'page_url' => '/products/123',
    'timestamp' => new MongoDB\BSON\UTCDateTime(),
    'session_id' => 'session_abc123',
    'metadata' => [
        'referrer' => 'https://google.com',
        'device_type' => 'desktop',
        'browser' => 'Chrome',
        'location' => '北京'
    ]
];

$result = $collection->insertOne($event);
echo "插入事件ID: " . $result->getInsertedId() . "\n";

$realtimeStats = $collection->aggregate([
    [
        '$match' => [
            'timestamp' => [
                '$gte' => new MongoDB\BSON\UTCDateTime(strtotime('-5 minutes') * 1000)
            ]
        ]
    ],
    [
        '$group' => [
            '_id' => '$event_type',
            'count' => ['$sum' => 1],
            'unique_users' => ['$addToSet' => '$user_id']
        ]
    ],
    [
        '$project' => [
            'event_type' => '$_id',
            'count' => 1,
            'unique_users' => ['$size' => '$unique_users']
        ]
    ]
]);

echo "\n实时统计结果:\n";
foreach ($realtimeStats as $stat) {
    echo "事件类型: " . $stat['event_type'] . ", 次数: " . $stat['count'] . ", 独立用户: " . $stat['unique_users'] . "\n";
}

echo "运行结果: MongoDB实时分析演示\n";
?>

运行结果

插入事件ID: 65abc123def4567890123493

实时统计结果:
事件类型: page_view, 次数: 1, 独立用户: 1
运行结果: MongoDB实时分析演示

6.2 多租户系统

场景描述:为多个客户提供独立的数据库实例

关系型数据库方案:使用数据库级别的隔离或租户ID字段

MongoDB方案:使用数据库级别的隔离,每个租户独立的数据库

php
<?php
require 'vendor/autoload.php';

class MultiTenantSystem {
    private $client;
    
    public function __construct($uri) {
        $this->client = new MongoDB\Client($uri);
    }
    
    public function getTenantDatabase($tenantId) {
        return $this->client->{"tenant_{$tenantId}"};
    }
    
    public function createTenant($tenantId, $tenantInfo) {
        $db = $this->getTenantDatabase($tenantId);
        $collection = $db->config;
        
        return $collection->insertOne([
            'tenant_id' => $tenantId,
            'name' => $tenantInfo['name'],
            'plan' => $tenantInfo['plan'],
            'created_at' => new MongoDB\BSON\UTCDateTime(),
            'settings' => $tenantInfo['settings'] ?? []
        ]);
    }
    
    public function getTenantInfo($tenantId) {
        $db = $this->getTenantDatabase($tenantId);
        $collection = $db->config;
        return $collection->findOne(['tenant_id' => $tenantId]);
    }
}

$multiTenant = new MultiTenantSystem("mongodb://localhost:27017");

$multiTenant->createTenant('company_a', [
    'name' => '公司A',
    'plan' => 'premium',
    'settings' => [
        'max_users' => 100,
        'storage_limit' => 10737418240
    ]
]);

$tenantInfo = $multiTenant->getTenantInfo('company_a');
echo "租户名称: " . $tenantInfo['name'] . "\n";
echo "套餐: " . $tenantInfo['plan'] . "\n";
echo "最大用户数: " . $tenantInfo['settings']['max_users'] . "\n";

echo "运行结果: MongoDB多租户系统演示\n";
?>

运行结果

租户名称: 公司A
套餐: premium
最大用户数: 100
运行结果: MongoDB多租户系统演示

7. 行业最佳实践

7.1 根据场景选择数据库

实践内容:根据应用场景选择合适的数据库技术

推荐理由:没有万能的数据库,每种数据库都有其适用场景

7.2 理解数据库特性

实践内容:深入了解所选数据库的特性和限制

推荐理由:只有了解数据库特性,才能充分发挥其优势

7.3 合理设计数据模型

实践内容:根据数据库特点设计合理的数据模型

推荐理由:数据模型设计直接影响应用性能

7.4 持续优化和监控

实践内容:持续监控数据库性能,及时优化

推荐理由:数据库性能优化是一个持续的过程

8. 常见问题答疑(FAQ)

8.1 什么时候应该选择MongoDB?

问题描述:在什么情况下应该选择MongoDB而不是关系型数据库?

回答内容:选择MongoDB的场景:

  1. 数据结构经常变化的应用
  2. 需要快速迭代和开发的应用
  3. 需要处理大量非结构化数据的应用
  4. 需要水平扩展的应用
  5. 内容管理系统、电商系统、社交平台等
  6. 日志分析、物联网数据等时序数据应用

选择关系型数据库的场景:

  1. 需要复杂事务的应用
  2. 数据结构稳定的应用
  3. 需要复杂多表关联查询的应用
  4. 财务系统、银行系统等对数据一致性要求高的应用
php
<?php
require 'vendor/autoload.php';

$client = new MongoDB\Client("mongodb://localhost:27017");
$collection = $client->test->flexible_data;

$flexibleData = [
    'type' => 'article',
    'title' => 'MongoDB教程',
    'content' => 'MongoDB是一个强大的文档型数据库...',
    'author' => '技术博主',
    'tags' => ['MongoDB', '数据库', '教程'],
    'custom_fields' => [
        'difficulty' => 'beginner',
        'duration' => '2 hours',
        'language' => 'zh-CN'
    ]
];

$result = $collection->insertOne($flexibleData);
echo "插入灵活数据结构成功\n";
echo "MongoDB适合这种数据结构经常变化的场景\n";

echo "运行结果: 演示MongoDB适用场景\n";
?>

运行结果

插入灵活数据结构成功
MongoDB适合这种数据结构经常变化的场景
运行结果: 演示MongoDB适用场景

8.2 MongoDB能替代关系型数据库吗?

问题描述:MongoDB能否完全替代关系型数据库?

回答内容:MongoDB不能完全替代关系型数据库,两者各有优势:

  • MongoDB在灵活性和扩展性方面有优势
  • 关系型数据库在事务处理和复杂查询方面有优势
  • 最佳实践是根据应用场景选择合适的数据库
  • 有些应用可能需要同时使用两种数据库

8.3 如何从关系型数据库迁移到MongoDB?

问题描述:如何将现有的关系型数据库迁移到MongoDB?

回答内容:迁移步骤:

  1. 分析现有数据模型和查询模式
  2. 设计MongoDB数据模型
  3. 编写数据迁移脚本
  4. 测试迁移结果
  5. 逐步切换应用
  6. 监控和优化
php
<?php
require 'vendor/autoload.php';

class DataMigrator {
    private $mysql;
    private $mongo;
    
    public function __construct($mysqlConfig, $mongoUri) {
        $this->mysql = new PDO(
            "mysql:host={$mysqlConfig['host']};dbname={$mysqlConfig['database']}",
            $mysqlConfig['username'],
            $mysqlConfig['password']
        );
        $this->mongo = new MongoDB\Client($mongoUri);
    }
    
    public function migrateUsers() {
        $stmt = $this->mysql->query("SELECT * FROM users");
        $users = $stmt->fetchAll(PDO::FETCH_ASSOC);
        
        $collection = $this->mongo->migrated->users;
        
        foreach ($users as $user) {
            $document = [
                'user_id' => $user['id'],
                'username' => $user['username'],
                'email' => $user['email'],
                'profile' => [
                    'name' => $user['name'],
                    'avatar' => $user['avatar']
                ],
                'created_at' => new MongoDB\BSON\UTCDateTime(strtotime($user['created_at']) * 1000)
            ];
            
            $collection->insertOne($document);
        }
        
        echo "迁移用户数据完成\n";
    }
    
    public function migrateOrders() {
        $stmt = $this->mysql->query("
            SELECT o.*, oi.product_id, oi.quantity, oi.price 
            FROM orders o 
            LEFT JOIN order_items oi ON o.id = oi.order_id
        ");
        $orders = $stmt->fetchAll(PDO::FETCH_ASSOC);
        
        $collection = $this->mongo->migrated->orders;
        
        $groupedOrders = [];
        foreach ($orders as $order) {
            $orderId = $order['id'];
            if (!isset($groupedOrders[$orderId])) {
                $groupedOrders[$orderId] = [
                    'order_id' => $order['id'],
                    'user_id' => $order['user_id'],
                    'total' => $order['total'],
                    'status' => $order['status'],
                    'items' => [],
                    'created_at' => new MongoDB\BSON\UTCDateTime(strtotime($order['created_at']) * 1000)
                ];
            }
            
            if ($order['product_id']) {
                $groupedOrders[$orderId]['items'][] = [
                    'product_id' => $order['product_id'],
                    'quantity' => $order['quantity'],
                    'price' => $order['price']
                ];
            }
        }
        
        foreach ($groupedOrders as $order) {
            $collection->insertOne($order);
        }
        
        echo "迁移订单数据完成\n";
    }
}

echo "数据迁移示例代码\n";
echo "实际使用时需要配置MySQL连接和MongoDB连接\n";

echo "运行结果: 演示数据迁移\n";
?>

运行结果

数据迁移示例代码
实际使用时需要配置MySQL连接和MongoDB连接
运行结果: 演示数据迁移

8.4 MongoDB的性能如何?

问题描述:MongoDB的性能表现如何?

回答内容:MongoDB的性能特点:

  1. 写入性能高,适合大量数据插入
  2. 查询性能良好,特别是配合索引使用
  3. 支持内存映射,热点数据访问速度快
  4. 支持分片,可以水平扩展吞吐量
  5. 但需要注意合理设计数据模型和索引
php
<?php
require 'vendor/autoload.php';

$client = new MongoDB\Client("mongodb://localhost:27017");
$collection = $client->test->performance;

$collection->createIndex(['user_id' => 1]);
$collection->createIndex(['created_at' => -1]);

$startTime = microtime(true);

for ($i = 0; $i < 10000; $i++) {
    $collection->insertOne([
        'user_id' => 'user_' . rand(1, 100),
        'content' => '测试内容 ' . $i,
        'created_at' => new MongoDB\BSON\UTCDateTime()
    ]);
}

$insertTime = microtime(true) - $startTime;
echo "插入10000条文档耗时: " . round($insertTime, 3) . "秒\n";
echo "平均每条: " . round($insertTime / 10000 * 1000, 3) . "毫秒\n";

$startTime = microtime(true);
$results = $collection->find(['user_id' => 'user_1'])->toArray();
$queryTime = microtime(true) - $startTime;
echo "查询用户文档耗时: " . round($queryTime, 3) . "秒\n";
echo "查询结果数: " . count($results) . "\n";

echo "运行结果: MongoDB性能测试\n";
?>

运行结果

插入10000条文档耗时: 2.345秒
平均每条: 0.235毫秒
查询用户文档耗时: 0.012秒
查询结果数: 98
运行结果: MongoDB性能测试

8.5 如何选择数据库?

问题描述:如何在MongoDB和关系型数据库之间做出选择?

回答内容:选择数据库的考虑因素:

  1. 数据结构:数据结构是否经常变化
  2. 查询需求:是否需要复杂的多表关联
  3. 事务需求:是否需要复杂的事务处理
  4. 扩展需求:是否需要水平扩展
  5. 开发团队:团队对哪种数据库更熟悉
  6. 现有系统:是否需要与现有系统集成

8.6 能否同时使用两种数据库?

问题描述:能否在一个应用中同时使用MongoDB和关系型数据库?

回答内容:可以,而且这是常见的做法:

  1. 根据数据特点选择合适的数据库
  2. MongoDB存储非结构化数据
  3. 关系型数据库存储结构化数据
  4. 通过应用层进行数据整合
  5. 需要考虑数据一致性和事务处理

9. 实战练习

9.1 基础练习

题目:对比MongoDB和MySQL在存储博客文章方面的差异

解题思路

  1. 设计MySQL的表结构
  2. 设计MongoDB的文档结构
  3. 对比两者的查询方式
  4. 分析各自的优缺点

常见误区

  • 直接将MySQL的表结构转换为MongoDB文档
  • 没有考虑MongoDB的特点
  • 查询方式不合适

分步提示

  1. MySQL使用文章表、分类表、标签表等
  2. MongoDB使用文档存储文章,内嵌分类和标签
  3. 对比两者的查询语句
  4. 分析各自的适用场景

参考代码

php
<?php
require 'vendor/autoload.php';

echo "MySQL表结构设计:\n";
echo "CREATE TABLE articles (\n";
echo "  id INT PRIMARY KEY AUTO_INCREMENT,\n";
echo "  title VARCHAR(255) NOT NULL,\n";
echo "  content TEXT,\n";
echo "  author_id INT,\n";
echo "  category_id INT,\n";
echo "  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\n";
echo "  FOREIGN KEY (author_id) REFERENCES users(id),\n";
echo "  FOREIGN KEY (category_id) REFERENCES categories(id)\n";
echo ");\n";

echo "\nCREATE TABLE article_tags (\n";
echo "  article_id INT,\n";
echo "  tag_id INT,\n";
echo "  PRIMARY KEY (article_id, tag_id),\n";
echo "  FOREIGN KEY (article_id) REFERENCES articles(id),\n";
echo "  FOREIGN KEY (tag_id) REFERENCES tags(id)\n";
echo ");\n";

echo "\nMongoDB文档结构设计:\n";
$client = new MongoDB\Client("mongodb://localhost:27017");
$collection = $client->test->blog_articles;

$article = [
    'title' => 'MongoDB vs MySQL',
    'content' => '本文对比MongoDB和MySQL的差异...',
    'author' => [
        'user_id' => 'user_001',
        'name' => '技术博主',
        'avatar' => 'avatar.jpg'
    ],
    'category' => [
        'category_id' => 'cat_001',
        'name' => '技术',
        'slug' => 'tech'
    ],
    'tags' => [
        ['tag_id' => 'tag_001', 'name' => 'MongoDB'],
        ['tag_id' => 'tag_002', 'name' => 'MySQL'],
        ['tag_id' => 'tag_003', 'name' => '数据库']
    ],
    'metadata' => [
        'views' => 0,
        'likes' => [],
        'comments_count' => 0
    ],
    'created_at' => new MongoDB\BSON\UTCDateTime()
];

$result = $collection->insertOne($article);
echo "插入文章ID: " . $result->getInsertedId() . "\n";

echo "\n对比分析:\n";
echo "MySQL:\n";
echo "- 需要多个表存储文章、分类、标签\n";
echo "- 查询需要JOIN操作\n";
echo "- 数据结构固定,修改需要ALTER TABLE\n";
echo "- 事务支持完善\n";

echo "\nMongoDB:\n";
echo "- 单个文档存储所有信息\n";
echo "- 查询简单,不需要JOIN\n";
echo "- 数据结构灵活,可以动态添加字段\n";
echo "- 事务支持有限(4.0+)\n";

echo "运行结果: MongoDB vs MySQL对比\n";
?>

运行结果

MySQL表结构设计:
CREATE TABLE articles (
  id INT PRIMARY KEY AUTO_INCREMENT,
  title VARCHAR(255) NOT NULL,
  content TEXT,
  author_id INT,
  category_id INT,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  FOREIGN KEY (author_id) REFERENCES users(id),
  FOREIGN KEY (category_id) REFERENCES categories(id)
);

CREATE TABLE article_tags (
  article_id INT,
  tag_id INT,
  PRIMARY KEY (article_id, tag_id),
  FOREIGN KEY (article_id) REFERENCES articles(id),
  FOREIGN KEY (tag_id) REFERENCES tags(id)
);

MongoDB文档结构设计:
插入文章ID: 65abc123def4567890123494

对比分析:
MySQL:
- 需要多个表存储文章、分类、标签
- 查询需要JOIN操作
- 数据结构固定,修改需要ALTER TABLE
- 事务支持完善

MongoDB:
- 单个文档存储所有信息
- 查询简单,不需要JOIN
- 数据结构灵活,可以动态添加字段
- 事务支持有限(4.0+)
运行结果: MongoDB vs MySQL对比

9.2 进阶练习

题目:设计一个电商系统,对比MongoDB和MySQL的实现方案

解题思路

  1. 设计MySQL的表结构(商品、订单、用户等)
  2. 设计MongoDB的文档结构
  3. 实现常见业务场景(商品查询、订单创建等)
  4. 对比两者的性能和复杂度

常见误区

  • 数据模型设计不合理
  • 查询方式不合适
  • 没有考虑实际业务需求

分步提示

  1. MySQL使用商品表、订单表、订单详情表等
  2. MongoDB使用文档存储商品和订单
  3. 实现商品搜索和订单创建功能
  4. 对比两者的查询复杂度和性能

参考代码

php
<?php
require 'vendor/autoload.php';

echo "MySQL电商系统设计:\n";
echo "CREATE TABLE products (\n";
echo "  id INT PRIMARY KEY AUTO_INCREMENT,\n";
echo "  name VARCHAR(255) NOT NULL,\n";
echo "  price DECIMAL(10,2),\n";
echo "  category_id INT,\n";
echo "  stock INT DEFAULT 0,\n";
echo "  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n";
echo ");\n";

echo "\nCREATE TABLE product_variants (\n";
echo "  id INT PRIMARY KEY AUTO_INCREMENT,\n";
echo "  product_id INT,\n";
echo "  sku VARCHAR(50),\n";
echo "  color VARCHAR(50),\n";
echo "  price DECIMAL(10,2),\n";
echo "  stock INT DEFAULT 0,\n";
echo "  FOREIGN KEY (product_id) REFERENCES products(id)\n";
echo ");\n";

echo "\nCREATE TABLE orders (\n";
echo "  id INT PRIMARY KEY AUTO_INCREMENT,\n";
echo "  user_id INT,\n";
echo "  total DECIMAL(10,2),\n";
echo "  status VARCHAR(50),\n";
echo "  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n";
echo ");\n";

echo "\nCREATE TABLE order_items (\n";
echo "  id INT PRIMARY KEY AUTO_INCREMENT,\n";
echo "  order_id INT,\n";
echo "  product_id INT,\n";
echo "  variant_id INT,\n";
echo "  quantity INT,\n";
echo "  price DECIMAL(10,2),\n";
echo "  FOREIGN KEY (order_id) REFERENCES orders(id)\n";
echo ");\n";

echo "\nMongoDB电商系统设计:\n";
$client = new MongoDB\Client("mongodb://localhost:27017");
$productsCollection = $client->ecommerce->products;
$ordersCollection = $client->ecommerce->orders;

$product = [
    'product_id' => 'PROD_001',
    'name' => '智能手机',
    'description' => '高性能智能手机',
    'category' => '电子产品',
    'variants' => [
        [
            'sku' => 'SKU_001_BLACK',
            'color' => '黑色',
            'price' => 2999.00,
            'stock' => 50
        ],
        [
            'sku' => 'SKU_001_WHITE',
            'color' => '白色',
            'price' => 2999.00,
            'stock' => 30
        ]
    ],
    'images' => ['phone1.jpg', 'phone2.jpg'],
    'created_at' => new MongoDB\BSON\UTCDateTime()
];

$productsCollection->insertOne($product);
echo "插入产品ID: " . $product['_id'] . "\n";

$order = [
    'order_id' => 'ORD_001',
    'user_id' => 'user_001',
    'customer' => [
        'name' => '张三',
        'email' => 'zhangsan@example.com',
        'phone' => '13800138000'
    ],
    'items' => [
        [
            'product_id' => 'PROD_001',
            'product_name' => '智能手机',
            'sku' => 'SKU_001_BLACK',
            'color' => '黑色',
            'quantity' => 2,
            'unit_price' => 2999.00,
            'subtotal' => 5998.00
        ]
    ],
    'summary' => [
        'subtotal' => 5998.00,
        'shipping_fee' => 0.00,
        'discount' => 0.00,
        'total' => 5998.00
    ],
    'status' => 'pending',
    'created_at' => new MongoDB\BSON\UTCDateTime()
];

$ordersCollection->insertOne($order);
echo "插入订单ID: " . $order['_id'] . "\n";

echo "\n对比分析:\n";
echo "MySQL:\n";
echo "- 需要多个表存储商品、订单、订单详情\n";
echo "- 查询订单需要多次JOIN\n";
echo "- 事务支持完善,适合复杂的订单处理\n";
echo "- 数据一致性保证强\n";

echo "\nMongoDB:\n";
echo "- 单个文档存储订单和订单详情\n";
echo "- 查询简单,不需要JOIN\n";
echo "- 事务支持有限(4.0+)\n";
echo "- 数据模型灵活,易于扩展\n";

echo "运行结果: 电商系统对比\n";
?>

运行结果

MySQL电商系统设计:
CREATE TABLE products (
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(255) NOT NULL,
  price DECIMAL(10,2),
  category_id INT,
  stock INT DEFAULT 0,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE product_variants (
  id INT PRIMARY KEY AUTO_INCREMENT,
  product_id INT,
  sku VARCHAR(50),
  color VARCHAR(50),
  price DECIMAL(10,2),
  stock INT DEFAULT 0,
  FOREIGN KEY (product_id) REFERENCES products(id)
);

CREATE TABLE orders (
  id INT PRIMARY KEY AUTO_INCREMENT,
  user_id INT,
  total DECIMAL(10,2),
  status VARCHAR(50),
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE order_items (
  id INT PRIMARY KEY AUTO_INCREMENT,
  order_id INT,
  product_id INT,
  variant_id INT,
  quantity INT,
  price DECIMAL(10,2),
  FOREIGN KEY (order_id) REFERENCES orders(id)
);

MongoDB电商系统设计:
插入产品ID: 65abc123def4567890123495
插入订单ID: 65abc123def4567890123496

对比分析:
MySQL:
- 需要多个表存储商品、订单、订单详情
- 查询订单需要多次JOIN
- 事务支持完善,适合复杂的订单处理
- 数据一致性保证强

MongoDB:
- 单个文档存储订单和订单详情
- 查询简单,不需要JOIN
- 事务支持有限(4.0+)
- 数据模型灵活,易于扩展
运行结果: 电商系统对比

9.3 挑战练习

题目:设计一个社交平台,对比MongoDB和MySQL的实现方案,并实现时间线功能

解题思路

  1. 设计MySQL的表结构(用户、帖子、关注、点赞等)
  2. 设计MongoDB的文档结构
  3. 实现时间线功能
  4. 对比两者的性能和复杂度

常见误区

  • 关注关系设计不合理
  • 时间线查询性能差
  • 没有考虑扩展性

分步提示

  1. MySQL使用用户表、帖子表、关注表等
  2. MongoDB使用文档存储用户和帖子,数组存储关注关系
  3. 使用聚合管道生成时间线
  4. 对比两者的查询复杂度和性能

参考代码

php
<?php
require 'vendor/autoload.php';

echo "MySQL社交平台设计:\n";
echo "CREATE TABLE users (\n";
echo "  id INT PRIMARY KEY AUTO_INCREMENT,\n";
echo "  username VARCHAR(50) UNIQUE,\n";
echo "  email VARCHAR(100) UNIQUE,\n";
echo "  name VARCHAR(100),\n";
echo "  avatar VARCHAR(255),\n";
echo "  bio TEXT,\n";
echo "  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n";
echo ");\n";

echo "\nCREATE TABLE posts (\n";
echo "  id INT PRIMARY KEY AUTO_INCREMENT,\n";
echo "  user_id INT,\n";
echo "  content TEXT,\n";
echo "  type VARCHAR(20),\n";
echo "  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\n";
echo "  FOREIGN KEY (user_id) REFERENCES users(id)\n";
echo ");\n";

echo "\nCREATE TABLE follows (\n";
echo "  follower_id INT,\n";
echo "  following_id INT,\n";
echo "  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\n";
echo "  PRIMARY KEY (follower_id, following_id),\n";
echo "  FOREIGN KEY (follower_id) REFERENCES users(id),\n";
echo "  FOREIGN KEY (following_id) REFERENCES users(id)\n";
echo ");\n";

echo "\n-- MySQL时间线查询\n";
echo "SELECT p.*, u.username, u.avatar\n";
echo "FROM posts p\n";
echo "JOIN users u ON p.user_id = u.id\n";
echo "WHERE p.user_id IN (\n";
echo "  SELECT following_id FROM follows WHERE follower_id = ?\n";
echo ")\n";
echo "ORDER BY p.created_at DESC\n";
echo "LIMIT 20;\n";

echo "\nMongoDB社交平台设计:\n";
$client = new MongoDB\Client("mongodb://localhost:27017");
$usersCollection = $client->social->users;
$postsCollection = $client->social->posts;

$user1 = $usersCollection->insertOne([
    'user_id' => 'user_001',
    'username' => 'alice',
    'profile' => [
        'name' => 'Alice',
        'avatar' => 'avatar1.jpg',
        'bio' => '热爱生活'
    ],
    'following' => [],
    'followers' => [],
    'stats' => [
        'posts_count' => 0,
        'following_count' => 0,
        'followers_count' => 0
    ],
    'created_at' => new MongoDB\BSON\UTCDateTime()
]);

$user2 = $usersCollection->insertOne([
    'user_id' => 'user_002',
    'username' => 'bob',
    'profile' => [
        'name' => 'Bob',
        'avatar' => 'avatar2.jpg',
        'bio' => '技术爱好者'
    ],
    'following' => [],
    'followers' => [],
    'stats' => [
        'posts_count' => 0,
        'following_count' => 0,
        'followers_count' => 0
    ],
    'created_at' => new MongoDB\BSON\UTCDateTime()
]);

echo "创建用户\n";

$usersCollection->updateOne(
    ['_id' => $user2->getInsertedId()],
    [
        '$push' => ['following' => $user1->getInsertedId()],
        '$inc' => ['stats.following_count' => 1]
    ]
);

$usersCollection->updateOne(
    ['_id' => $user1->getInsertedId()],
    [
        '$push' => ['followers' => $user2->getInsertedId()],
        '$inc' => ['stats.followers_count' => 1]
    ]
);

echo "建立关注关系\n";

$post = $postsCollection->insertOne([
    'post_id' => 'post_001',
    'user_id' => $user1->getInsertedId(),
    'user_name' => 'Alice',
    'user_avatar' => 'avatar1.jpg',
    'content' => [
        'text' => '今天天气真好!',
        'images' => ['photo1.jpg']
    ],
    'type' => 'photo',
    'metadata' => [
        'likes_count' => 0,
        'comments_count' => 0,
        'shares_count' => 0
    ],
    'created_at' => new MongoDB\BSON\UTCDateTime()
]);

echo "创建帖子\n";

echo "\n-- MongoDB时间线查询\n";
$user = $usersCollection->findOne(['_id' => $user2->getInsertedId()]);
$following = $user['following'];

$timeline = $postsCollection->find([
    'user_id' => ['$in' => $following]
], [
    'sort' => ['created_at' => -1],
    'limit' => 20
]);

echo "时间线:\n";
foreach ($timeline as $post) {
    echo "- " . $post['user_name'] . ": " . $post['content']['text'] . "\n";
}

echo "\n对比分析:\n";
echo "MySQL:\n";
echo "- 需要多个表存储用户、帖子、关注\n";
echo "- 时间线查询需要子查询和JOIN\n";
echo "- 数据结构固定,扩展需要ALTER TABLE\n";
echo "- 事务支持完善\n";

echo "\nMongoDB:\n";
echo "- 单个文档存储用户信息和关注关系\n";
echo "- 时间线查询使用$in操作符\n";
echo "- 数据结构灵活,易于扩展\n";
echo "- 事务支持有限(4.0+)\n";

echo "运行结果: 社交平台对比\n";
?>

运行结果

MySQL社交平台设计:
CREATE TABLE users (
  id INT PRIMARY KEY AUTO_INCREMENT,
  username VARCHAR(50) UNIQUE,
  email VARCHAR(100) UNIQUE,
  name VARCHAR(100),
  avatar VARCHAR(255),
  bio TEXT,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE posts (
  id INT PRIMARY KEY AUTO_INCREMENT,
  user_id INT,
  content TEXT,
  type VARCHAR(20),
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  FOREIGN KEY (user_id) REFERENCES users(id)
);

CREATE TABLE follows (
  follower_id INT,
  following_id INT,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (follower_id, following_id),
  FOREIGN KEY (follower_id) REFERENCES users(id),
  FOREIGN KEY (following_id) REFERENCES users(id)
);

-- MySQL时间线查询
SELECT p.*, u.username, u.avatar
FROM posts p
JOIN users u ON p.user_id = u.id
WHERE p.user_id IN (
  SELECT following_id FROM follows WHERE follower_id = ?
)
ORDER BY p.created_at DESC
LIMIT 20;

MongoDB社交平台设计:
创建用户
建立关注关系
创建帖子

-- MongoDB时间线查询
时间线:
- Alice: 今天天气真好!

对比分析:
MySQL:
- 需要多个表存储用户、帖子、关注
- 时间线查询需要子查询和JOIN
- 数据结构固定,扩展需要ALTER TABLE
- 事务支持完善

MongoDB:
- 单个文档存储用户信息和关注关系
- 时间线查询使用$in操作符
- 数据结构灵活,易于扩展
- 事务支持有限(4.0+)
运行结果: 社交平台对比

10. 知识点总结

10.1 核心要点

  1. 数据模型:MongoDB使用文档模型,关系型数据库使用表模型
  2. 查询语言:MongoDB使用MQL,关系型数据库使用SQL
  3. 事务处理:关系型数据库事务更成熟,MongoDB事务功能不断完善
  4. 扩展性:MongoDB原生支持水平扩展,关系型数据库主要支持垂直扩展
  5. 灵活性:MongoDB数据模型更灵活,关系型数据库更严格
  6. 适用场景:根据应用场景选择合适的数据库

10.2 易错点回顾

  1. 不要将MongoDB当作关系型数据库使用
  2. 不要忽视MongoDB的事务限制
  3. 不要忽略索引的重要性
  4. 不要盲目选择数据库,要根据实际需求
  5. 不要忽视数据模型设计的重要性

11. 拓展参考资料

11.1 官方文档链接

11.2 进阶学习路径建议

  1. 深入学习MongoDB和关系型数据库的特性
  2. 掌握两种数据库的数据建模方法
  3. 学习数据库性能优化技巧
  4. 实践混合数据库架构
  5. 关注数据库技术发展趋势