当前位置: 首页 > news >正文

Node.js面试题及详细答案120题(69-80) -- 数据库操作篇

前后端面试题》专栏集合了前后端各个知识模块的面试题,包括html,javascript,css,vue,react,java,Openlayers,leaflet,cesium,mapboxGL,threejs,nodejs,mangoDB,MySQL,Linux… 。

前后端面试题-专栏总目录

在这里插入图片描述

文章目录

  • 一、本文面试题目录
      • 69. Node.js中常用的数据库有哪些?请举例说明其适用场景。
      • 70. 如何使用Node.js连接MySQL数据库?请写出基本操作代码。
        • 步骤1:安装依赖
        • 步骤2:基本操作代码
      • 71. 如何使用Node.js连接MongoDB数据库?Mongoose有什么作用?
        • 方法1:使用`mongodb`原生驱动
        • 方法2:使用Mongoose(推荐)
      • 72. 什么是ORM?Sequelize的作用是什么?
      • 73. 如何处理数据库操作中的异步错误?
        • 1. 使用`try/catch`配合`async/await`(推荐)
        • 2. 使用Promise的`catch()`方法
        • 3. 回调函数中的错误处理
        • 关键处理原则
      • 74. 什么是连接池?在Node.js中如何配置数据库连接池?
        • 在Node.js中配置数据库连接池
          • 1. MySQL连接池(`mysql2`)
          • 2. MongoDB连接池(`mongodb`驱动)
          • 3. Sequelize连接池配置
      • 75. 如何防止SQL注入?在Node.js中有哪些措施?
        • 1. 使用参数化查询(Prepared Statements)
        • 2. 避免动态拼接SQL
        • 3. 使用ORM/查询构建器
        • 4. 限制数据库用户权限
        • 5. 输入验证与过滤
        • 6. 使用存储过程(谨慎)
      • 76. 什么是事务?在Node.js中如何实现数据库事务?
        • 在Node.js中实现数据库事务
          • 1. MySQL事务(`mysql2`)
          • 2. MongoDB事务(`mongodb`驱动)
          • 3. Sequelize事务
      • 77. 如何优化数据库查询性能?
        • 1. 合理设计索引
        • 2. 优化查询语句
        • 3. 数据分页与延迟加载
        • 4. 缓存查询结果
        • 5. 数据库优化
        • 6. 应用层优化
        • 7. 监控与调优
      • 78. 什么是NoSQL数据库?它和关系型数据库有什么区别?
        • NoSQL与关系型数据库的核心区别
        • 常见NoSQL数据库类型及适用场景
        • 选择建议
      • 79. 如何使用Redis在Node.js中实现缓存?
        • 步骤1:安装依赖
        • 步骤2:基本缓存实现
        • 缓存策略关键点
      • 80. 什么是ORM和OODM?它们的区别是什么?
        • 定义与核心作用
        • 区别对比
        • 总结
  • 二、120道Node.js面试题目录列表

一、本文面试题目录

69. Node.js中常用的数据库有哪些?请举例说明其适用场景。

Node.js 生态支持多种数据库,根据数据模型可分为关系型数据库、NoSQL 数据库等,选择需结合业务场景:

  1. 关系型数据库

    • MySQL:开源关系型数据库,支持复杂 SQL 查询和事务,适合结构化数据(如用户信息、订单系统)。
    • PostgreSQL:功能强大的开源数据库,支持 JSON 数据类型和复杂查询,适合需要扩展性和数据完整性的场景(如金融系统)。
    • SQLite:轻量级嵌入式数据库,无需独立服务,适合本地应用或开发环境(如桌面工具、移动端同步)。
  2. NoSQL 数据库

    • MongoDB:文档型数据库,存储 JSON 格式文档,适合非结构化/半结构化数据(如日志、内容管理系统)。
    • Redis:内存型键值数据库,支持多种数据结构(字符串、哈希、列表等),适合缓存、会话存储、实时统计。
    • Cassandra:分布式列存储数据库,高可用、高吞吐量,适合海量数据写入(如物联网数据、日志系统)。
    • CouchDB:面向文档的数据库,支持 REST API 和版本控制,适合需要离线同步的场景(如协作工具)。
  3. 其他类型

    • Neo4j:图形数据库,适合存储实体间关系(如社交网络、知识图谱)。
    • LevelDB:轻量级键值存储,适合简单的本地数据持久化(如日志存储)。

场景示例

  • 电商订单系统 → MySQL(事务支持、结构化数据)。
  • 实时聊天消息缓存 → Redis(高性能、支持列表结构)。
  • 内容管理平台 → MongoDB(灵活存储不同结构的文章/视频数据)。
  • 社交关系网络 → Neo4j(高效查询用户间关系)。

70. 如何使用Node.js连接MySQL数据库?请写出基本操作代码。

Node.js 连接 MySQL 常用 mysql2 库(支持 Promise 和连接池,性能优于旧版 mysql),以下是基本操作示例:

步骤1:安装依赖
npm install mysql2
步骤2:基本操作代码
const mysql = require('mysql2/promise'); // 使用Promise API// 数据库配置
const config = {host: 'localhost',user: 'root',password: 'your_password',database: 'test_db',port: 3306
};// 连接数据库并执行操作
async function mysqlExample() {let connection;try {// 1. 建立连接connection = await mysql.createConnection(config);console.log('数据库连接成功');// 2. 创建表(若不存在)await connection.execute(`CREATE TABLE IF NOT EXISTS users (id INT AUTO_INCREMENT PRIMARY KEY,name VARCHAR(255) NOT NULL,age INT,created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP)`);console.log('表创建成功');// 3. 插入数据const [insertResult] = await connection.execute('INSERT INTO users (name, age) VALUES (?, ?)',['Alice', 25] // 参数化查询,防止SQL注入);console.log('插入成功,ID:', insertResult.insertId);// 4. 查询数据const [rows] = await connection.execute('SELECT * FROM users');console.log('查询结果:', rows);// 5. 更新数据await connection.execute('UPDATE users SET age = ? WHERE name = ?',[26, 'Alice']);console.log('更新成功');// 6. 删除数据await connection.execute('DELETE FROM users WHERE id = ?',[insertResult.insertId]);console.log('删除成功');} catch (err) {console.error('数据库操作错误:', err);} finally {// 7. 关闭连接if (connection) {await connection.end();console.log('连接已关闭');}}
}// 执行示例
mysqlExample();

关键说明

  • 使用 mysql2/promise 支持 async/await,简化异步操作。
  • 采用参数化查询(? 占位符)防止 SQL 注入。
  • 生产环境建议使用连接池(createPool)而非单次连接,提高性能。

71. 如何使用Node.js连接MongoDB数据库?Mongoose有什么作用?

MongoDB 是文档型 NoSQL 数据库,Node.js 中常用 mongodb 原生驱动或 mongoose ODM 连接,mongoose 提供更简洁的 schema 定义和中间件功能。

方法1:使用mongodb原生驱动
const { MongoClient } = require('mongodb');// 连接字符串
const uri = 'mongodb://localhost:27017';
const client = new MongoClient(uri);
const dbName = 'test_db';async function mongoExample() {try {// 连接数据库await client.connect();console.log('连接MongoDB成功');const db = client.db(dbName);const collection = db.collection('users');// 插入文档const insertResult = await collection.insertOne({name: 'Bob',age: 30,hobbies: ['reading', 'coding']});console.log('插入成功,ID:', insertResult.insertedId);// 查询文档const user = await collection.findOne({ name: 'Bob' });console.log('查询结果:', user);// 更新文档await collection.updateOne({ _id: insertResult.insertedId },{ $set: { age: 31 } });console.log('更新成功');// 删除文档await collection.deleteOne({ _id: insertResult.insertedId });console.log('删除成功');} catch (err) {console.error('MongoDB操作错误:', err);} finally {// 关闭连接await client.close();console.log('连接已关闭');}
}mongoExample();
方法2:使用Mongoose(推荐)

Mongoose 的作用

  • 定义 schema 约束文档结构,确保数据一致性。
  • 提供模型(Model)层抽象,简化 CRUD 操作。
  • 支持中间件(pre/post hooks)处理数据验证、转换等。
  • 提供查询构建器,简化复杂查询。

使用示例

npm install mongoose
const mongoose = require('mongoose');// 1. 连接数据库
mongoose.connect('mongodb://localhost:27017/test_db').then(() => console.log('Mongoose连接成功')).catch(err => console.error('连接失败:', err));// 2. 定义Schema
const userSchema = new mongoose.Schema({name: { type: String, required: true }, // 必选字段age: { type: Number, min: 0 }, // 数字类型,最小值0hobbies: [String], // 字符串数组created_at: { type: Date, default: Date.now } // 默认当前时间
});// 3. 创建模型(对应集合)
const User = mongoose.model('User', userSchema);// 4. 执行操作
async function mongooseExample() {try {// 插入const user = new User({ name: 'Charlie', age: 35, hobbies: ['gaming'] });await user.save();console.log('插入成功:', user._id);// 查询const foundUser = await User.findOne({ name: 'Charlie' });console.log('查询结果:', foundUser);// 更新await User.updateOne({ _id: user._id }, { age: 36 });// 删除await User.deleteOne({ _id: user._id });} catch (err) {console.error('Mongoose操作错误:', err);} finally {// 关闭连接await mongoose.disconnect();}
}mongooseExample();

72. 什么是ORM?Sequelize的作用是什么?

ORM(Object-Relational Mapping,对象关系映射) 是一种编程技术,将关系型数据库中的表映射为程序中的对象,通过操作对象实现对数据库的操作,无需编写原始 SQL。

核心优势

  • 屏蔽数据库差异,同一套代码可适配多种数据库(如 MySQL、PostgreSQL)。
  • 用面向对象语法(如 user.save())替代 SQL,简化开发。
  • 自动处理数据类型转换、关系映射(如一对一、一对多)。

Sequelize 的作用
Sequelize 是 Node.js 中流行的 ORM 库,支持 MySQL、PostgreSQL、SQLite 等数据库,主要功能包括:

  1. 定义数据模型(Model)映射数据库表。
  2. 提供链式查询 API,简化复杂 SQL 操作。
  3. 支持事务、关联查询(关联模型)。
  4. 自动生成迁移文件,管理数据库 schema 变更。
  5. 内置数据验证和钩子(hooks),处理数据预处理/后处理。

Sequelize 示例

npm install sequelize mysql2
const { Sequelize, DataTypes } = require('sequelize');// 1. 初始化Sequelize(连接数据库)
const sequelize = new Sequelize('test_db', 'root', 'your_password', {host: 'localhost',dialect: 'mysql' // 指定数据库类型
});// 2. 定义模型(对应users表)
const User = sequelize.define('User', {name: {type: DataTypes.STRING,allowNull: false // 不允许为null},age: {type: DataTypes.INTEGER,validate: { min: 0 } // 验证规则:年龄不能为负}
}, {tableName: 'users', // 显式指定表名timestamps: true // 自动添加createdAt和updatedAt字段
});// 3. 同步模型到数据库(创建表)
(async () => {await sequelize.sync({ force: false }); // force: true 会删除旧表重建console.log('模型同步完成');// 4. 操作数据try {// 创建用户const user = await User.create({ name: 'Dave', age: 40 });console.log('创建用户:', user.toJSON());// 查询用户const foundUser = await User.findOne({ where: { name: 'Dave' } });console.log('查询用户:', foundUser?.toJSON());// 更新用户await User.update({ age: 41 }, { where: { id: user.id } });// 删除用户await User.destroy({ where: { id: user.id } });} catch (err) {console.error('操作错误:', err);} finally {// 关闭连接await sequelize.close();}
})();

73. 如何处理数据库操作中的异步错误?

Node.js 数据库操作均为异步操作(回调、Promise 或 async/await),错误处理需防止未捕获异常导致程序崩溃,常用策略如下:

1. 使用try/catch配合async/await(推荐)

适用于 Promise 风格的数据库操作(如 mysql2/promise、Mongoose、Sequelize):

const { Sequelize } = require('sequelize');
const sequelize = new Sequelize('test_db', 'root', 'pass', { dialect: 'mysql' });async function safeOperation() {try {// 数据库操作const users = await sequelize.query('SELECT * FROM users');console.log('查询成功:', users);} catch (err) {// 捕获所有错误(连接错误、SQL错误等)console.error('操作失败:', err.message);// 进一步处理:重试、记录日志、返回友好提示if (err.name === 'SequelizeConnectionError') {console.error('数据库连接失败,检查配置');} else if (err.name === 'SequelizeQueryError') {console.error('SQL语法错误');}} finally {// 无论成功失败,确保资源释放await sequelize.close().catch(closeErr => {console.error('关闭连接失败:', closeErr);});}
}safeOperation();
2. 使用Promise的catch()方法

适用于链式调用的场景:

const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/test_db');
const User = mongoose.model('User', new mongoose.Schema({ name: String }));// 链式操作+catch捕获错误
User.findOne({ name: 'Invalid' }).then(user => {if (!user) throw new Error('用户不存在');console.log(user);}).catch(err => {console.error('错误:', err.message);// 处理错误:如返回404响应}).finally(() => mongoose.disconnect());
3. 回调函数中的错误处理

适用于回调风格的数据库库(如旧版 mysql):

const mysql = require('mysql');
const connection = mysql.createConnection({host: 'localhost',user: 'root',password: 'pass',database: 'test_db'
});// 连接错误处理
connection.connect(err => {if (err) {console.error('连接失败:', err.stack);return; // 终止执行}console.log('连接成功');
});// 查询错误处理
connection.query('SELECT * FROM invalid_table', (err, results) => {if (err) {console.error('查询错误:', err.message);connection.end(); // 出错后关闭连接return;}console.log(results);connection.end();
});
关键处理原则
  • 分层捕获:在数据访问层(DAO)捕获底层错误,转换为业务错误后抛给上层。
  • 详细日志:记录错误堆栈、时间、上下文(如SQL语句、参数),便于排查。
  • 资源释放:确保错误发生后关闭数据库连接、释放锁等资源(finally 块)。
  • 用户友好:对外暴露简化的错误信息(如“操作失败”),隐藏敏感细节(如数据库地址)。

74. 什么是连接池?在Node.js中如何配置数据库连接池?

连接池(Connection Pool) 是一组预先创建的数据库连接,供应用程序重复使用,避免频繁创建和关闭连接的性能开销(尤其对数据库来说,连接建立成本高)。

优势

  • 减少连接建立/关闭的耗时,提高响应速度。
  • 控制并发连接数,防止数据库过载。
  • 连接复用,降低资源消耗。
在Node.js中配置数据库连接池

不同数据库的连接池配置方式略有差异,以下是常见示例:

1. MySQL连接池(mysql2
const mysql = require('mysql2/promise');// 创建连接池
const pool = mysql.createPool({host: 'localhost',user: 'root',password: 'your_password',database: 'test_db',waitForConnections: true, // 连接不足时等待(而非报错)connectionLimit: 10, // 最大连接数queueLimit: 0 // 等待队列大小(0表示无限制)
});// 使用连接池
async function usePool() {let connection;try {// 从池获取连接connection = await pool.getConnection();// 执行查询const [rows] = await connection.execute('SELECT * FROM users');console.log('查询结果:', rows);} catch (err) {console.error('操作错误:', err);} finally {// 释放连接回池(而非关闭)if (connection) connection.release();}
}// 多次调用,复用连接
usePool();
usePool();
2. MongoDB连接池(mongodb驱动)
const { MongoClient } = require('mongodb');const uri = 'mongodb://localhost:27017';
const client = new MongoClient(uri, {maxPoolSize: 10, // 最大连接数minPoolSize: 2, // 最小连接数maxIdleTimeMS: 30000 // 连接空闲超时(30秒)
});async function useMongoPool() {try {await client.connect();const db = client.db('test_db');// 多次查询复用连接池中的连接const result1 = await db.collection('users').findOne();const result2 = await db.collection('posts').findOne();console.log('查询结果:', result1, result2);} catch (err) {console.error('错误:', err);} finally {// 关闭客户端(释放所有连接)await client.close();}
}useMongoPool();
3. Sequelize连接池配置
const { Sequelize } = require('sequelize');const sequelize = new Sequelize('test_db', 'root', 'pass', {host: 'localhost',dialect: 'mysql',pool: {max: 10, // 最大连接数min: 2, // 最小连接数acquire: 30000, // 获取连接的超时时间(30秒)idle: 10000 // 连接空闲超时(10秒)}
});// 测试连接池
sequelize.authenticate().then(() => console.log('连接池配置成功')).catch(err => console.error('配置失败:', err));

配置建议

  • connectionLimit(最大连接数):根据数据库性能和应用并发量设置(通常 10-50)。
  • 避免设置过大的连接数,否则会增加数据库负担。
  • 生产环境监控连接池状态(如空闲连接数、等待队列长度),动态调整配置。

75. 如何防止SQL注入?在Node.js中有哪些措施?

SQL注入是攻击者通过在输入中插入恶意SQL代码,篡改数据库查询逻辑(如删除表、泄露数据)的攻击方式。Node.js中可通过以下措施防止:

1. 使用参数化查询(Prepared Statements)

用占位符(? 或命名参数)代替直接拼接用户输入,数据库会自动处理参数转义。

示例(mysql2

// 危险:直接拼接用户输入(可能注入)
const unsafeQuery = `SELECT * FROM users WHERE name = '${userInput}'`;// 安全:参数化查询
const [rows] = await connection.execute('SELECT * FROM users WHERE name = ?', // 占位符?[userInput] // 参数数组
);

示例(Sequelize)

// 安全查询
const users = await User.findAll({where: { name: userInput } // Sequelize自动参数化
});
2. 避免动态拼接SQL

如需动态生成SQL(如动态排序字段),使用白名单限制允许的输入:

// 危险:直接使用用户输入作为字段名
const orderBy = userInput; // 若用户输入 "name; DROP TABLE users;" 则危险
const unsafeQuery = `SELECT * FROM users ORDER BY ${orderBy}`;// 安全:白名单校验
const allowedFields = ['name', 'age', 'created_at'];
const orderBy = allowedFields.includes(userInput) ? userInput : 'id'; // 默认值
const safeQuery = `SELECT * FROM users ORDER BY ${orderBy}`;
3. 使用ORM/查询构建器

ORM(如Sequelize)或查询构建器(如knex)会自动处理参数化,减少手动编写SQL的风险:

const knex = require('knex')({ client: 'mysql' });// 安全查询
const query = knex('users').where('name', userInput);
const rows = await query; // 生成参数化SQL
4. 限制数据库用户权限

遵循最小权限原则,应用连接数据库的用户仅授予必要权限(如SELECTINSERT),禁止DROPALTER等高危操作。

5. 输入验证与过滤

对用户输入进行类型校验和清洗(如限制长度、过滤特殊字符):

function validateInput(input) {// 仅允许字母、数字和空格return /^[a-zA-Z0-9\s]+$/.test(input);
}const userInput = req.query.name;
if (!validateInput(userInput)) {return res.status(400).send('无效输入');
}
6. 使用存储过程(谨慎)

若使用存储过程,确保内部也使用参数化查询,避免在存储过程中拼接输入。

关键原则:永远不要相信用户输入,所有外部数据必须经过验证和参数化处理后才能用于数据库操作。

76. 什么是事务?在Node.js中如何实现数据库事务?

事务(Transaction) 是数据库中一组不可分割的操作,要么全部成功执行,要么全部失败回滚,确保数据一致性(如转账时“扣款”和“入账”必须同时成功或失败)。

事务ACID特性

  • 原子性(Atomicity):操作要么全成,要么全败。
  • 一致性(Consistency):事务前后数据状态合法。
  • 隔离性(Isolation):并发事务互不干扰。
  • 持久性(Durability):事务成功后数据永久保存。
在Node.js中实现数据库事务

不同数据库的事务实现方式略有差异,以下是常见示例:

1. MySQL事务(mysql2
const mysql = require('mysql2/promise');
const pool = mysql.createPool({ /* 配置 */ });async function transferMoney(fromId, toId, amount) {const connection = await pool.getConnection();try {// 1. 开始事务await connection.beginTransaction();// 2. 执行操作(扣减转出账户)const [fromResult] = await connection.execute('UPDATE accounts SET balance = balance - ? WHERE id = ? AND balance >= ?',[amount, fromId, amount]);if (fromResult.affectedRows === 0) {throw new Error('转出账户余额不足或不存在');}// 3. 执行操作(增加转入账户)await connection.execute('UPDATE accounts SET balance = balance + ? WHERE id = ?',[amount, toId]);// 4. 提交事务(所有操作成功)await connection.commit();console.log('转账成功');return true;} catch (err) {// 5. 回滚事务(任何操作失败)await connection.rollback();console.error('转账失败,已回滚:', err);return false;} finally {// 释放连接connection.release();}
}// 调用事务
transferMoney(1, 2, 100);
2. MongoDB事务(mongodb驱动)

MongoDB 4.0+ 支持多文档事务:

const { MongoClient } = require('mongodb');
const client = new MongoClient('mongodb://localhost:27017');async function transfer() {await client.connect();const session = client.startSession(); // 创建事务会话try {// 开始事务session.startTransaction();const accounts = client.db('bank').collection('accounts');// 扣减余额await accounts.updateOne({ _id: 1 },{ $inc: { balance: -100 } },{ session } // 指定会话);// 增加余额await accounts.updateOne({ _id: 2 },{ $inc: { balance: 100 } },{ session });// 提交事务await session.commitTransaction();console.log('事务提交成功');} catch (err) {// 回滚事务await session.abortTransaction();console.error('事务回滚:', err);} finally {session.endSession();await client.close();}
}transfer();
3. Sequelize事务
const { Sequelize } = require('sequelize');
const sequelize = new Sequelize('test_db', 'root', 'pass', { dialect: 'mysql' });
const Account = sequelize.define('Account', { balance: Sequelize.INTEGER });async function sequelizeTransfer() {// 开始事务const transaction = await sequelize.transaction();try {// 扣减await Account.update({ balance: Sequelize.literal(`balance - 100`) },{ where: { id: 1 }, transaction });// 增加await Account.update({ balance: Sequelize.literal(`balance + 100`) },{ where: { id: 2 }, transaction });// 提交await transaction.commit();} catch (err) {// 回滚await transaction.rollback();}
}

注意事项

  • 事务应尽量简短,避免长时间占用锁资源。
  • 确保操作的表/集合支持事务(如MySQL的InnoDB引擎)。
  • 并发事务需考虑隔离级别(如读未提交、读已提交),避免脏读、幻读等问题。

77. 如何优化数据库查询性能?

数据库查询性能直接影响应用响应速度,优化需从查询语句、索引、数据结构等多方面入手:

1. 合理设计索引
  • 创建必要索引:对查询频繁的字段(如WHEREJOINORDER BY涉及的字段)创建索引。
    -- 为用户表的name字段创建索引
    CREATE INDEX idx_users_name ON users(name);
    
  • 避免过度索引:索引会减慢写入操作(INSERT/UPDATE/DELETE),仅为常用查询创建索引。
  • 复合索引:多字段查询时,创建复合索引(注意字段顺序,选择性高的字段放前面)。
    -- 对age和name创建复合索引(适合WHERE age=? AND name=?)
    CREATE INDEX idx_users_age_name ON users(age, name);
    
2. 优化查询语句
  • 避免SELECT *:只查询需要的字段,减少数据传输和内存占用。
    -- 差:查询所有字段
    SELECT * FROM users WHERE age > 30;
    -- 好:只查询需要的字段
    SELECT id, name FROM users WHERE age > 30;
    
  • 限制结果集大小:用LIMIT分页,避免返回大量数据。
    SELECT * FROM users LIMIT 10 OFFSET 20; -- 分页查询
    
  • 避免JOIN过多表:多表连接会增加查询复杂度,必要时考虑数据冗余或分查。
  • EXPLAIN分析查询计划:识别全表扫描、索引失效等问题。
    EXPLAIN SELECT * FROM users WHERE name = 'Alice';
    
3. 数据分页与延迟加载
  • 分页查询:通过LIMIT + OFFSET或游标分页(适合大数据量)。
  • 延迟加载:按需加载关联数据(如Mongoose的populate仅在需要时加载关联文档)。
4. 缓存查询结果
  • 用Redis缓存高频查询结果(如热门商品列表、首页数据)。
    const redis = require('redis');
    const client = redis.createClient();async function getUsers() {const cacheKey = 'users:list';// 先查缓存const cached = await client.get(cacheKey);if (cached) return JSON.parse(cached);// 缓存未命中,查数据库const users = await User.findAll();// 存入缓存(设置过期时间)await client.setEx(cacheKey, 3600, JSON.stringify(users));return users;
    }
    
5. 数据库优化
  • 分表分库:大表按时间、地区等拆分(如订单表按月份分表)。
  • 读写分离:主库负责写入,从库负责查询,分散压力。
  • 选择合适的存储引擎:如MySQL用InnoDB(支持事务),MongoDB用WiredTiger(高性能)。
6. 应用层优化
  • 批量操作:用批量插入/更新替代循环单条操作。
    // 好:批量插入
    await User.bulkCreate([{ name: 'A' }, { name: 'B' }]);
    
  • 避免N+1查询问题:一次查询关联数据,而非循环查询。
    // 差:N+1问题(1次查用户,N次查订单)
    const users = await User.findAll();
    for (const user of users) {const orders = await Order.findAll({ where: { userId: user.id } });
    }// 好:一次查询关联数据
    const users = await User.findAll({include: [{ model: Order }] // 关联查询
    });
    
7. 监控与调优
  • 监控慢查询日志(如MySQL的slow_query_log),定期分析优化。
  • 根据数据库性能指标(CPU、内存、IO)调整配置(如连接池大小、缓存区)。

78. 什么是NoSQL数据库?它和关系型数据库有什么区别?

NoSQL(Not Only SQL) 是一类非关系型数据库的统称,不依赖于固定的表结构(schema),适合存储非结构化或半结构化数据,支持高并发、高扩展性场景。

NoSQL与关系型数据库的核心区别
特性关系型数据库(如MySQL、PostgreSQL)NoSQL数据库(如MongoDB、Redis)
数据模型基于表和行,严格的schema约束多样(文档、键值、列族、图形),无固定schema
事务支持强事务支持(ACID)部分支持(如MongoDB 4.0+支持多文档事务)
扩展性垂直扩展为主(升级硬件),水平扩展复杂天然支持水平扩展(分片集群)
查询语言标准SQL无统一标准(如MongoDB用查询文档)
适用数据结构化数据(如用户信息、订单)非结构化/半结构化数据(如日志、JSON)
连接操作支持复杂JOIN查询通常不支持JOIN,需应用层处理
一致性强一致性最终一致性(部分支持强一致性)
常见NoSQL数据库类型及适用场景
  1. 文档型(如MongoDB)

    • 存储格式:JSON-like文档(BSON)。
    • 适用场景:内容管理(文章、评论)、日志存储。
  2. 键值型(如Redis)

    • 存储格式:键值对(支持字符串、哈希、列表等)。
    • 适用场景:缓存、会话存储、计数器。
  3. 列族型(如Cassandra)

    • 存储格式:按列族组织的分布式存储。
    • 适用场景:海量数据写入(物联网、日志)。
  4. 图形型(如Neo4j)

    • 存储格式:节点和关系组成的图形。
    • 适用场景:社交网络、知识图谱。
选择建议
  • 需强事务、结构化数据、复杂查询 → 关系型数据库。
  • 高并发写入、非结构化数据、水平扩展需求 → NoSQL。
  • 实际应用中常混合使用(如MySQL存储核心业务数据,Redis缓存,MongoDB存储日志)。

79. 如何使用Redis在Node.js中实现缓存?

Redis 是高性能的内存型键值数据库,适合作为缓存存储高频访问数据,减少数据库压力。Node.js 中常用 redis 库操作 Redis。

步骤1:安装依赖
npm install redis
步骤2:基本缓存实现
const redis = require('redis');
const { Sequelize, DataTypes } = require('sequelize');// 1. 连接Redis
const redisClient = redis.createClient({url: 'redis://localhost:6379' // Redis服务器地址
});
redisClient.connect().catch(console.error);// 2. 连接数据库(示例用Sequelize)
const sequelize = new Sequelize('test_db', 'root', 'pass', { dialect: 'mysql' });
const Product = sequelize.define('Product', {name: DataTypes.STRING,price: DataTypes.FLOAT
});// 3. 带缓存的查询函数
async function getProductById(id) {const cacheKey = `product:${id}`;// 先查Redis缓存const cachedData = await redisClient.get(cacheKey);if (cachedData) {console.log('从缓存获取数据');return JSON.parse(cachedData);}// 缓存未命中,查数据库console.log('从数据库获取数据');const product = await Product.findByPk(id);if (!product) return null;// 存入Redis,设置过期时间(10分钟)await redisClient.setEx(cacheKey,600, // 过期时间(秒)JSON.stringify(product.toJSON()));return product;
}// 4. 更新数据时同步更新缓存
async function updateProduct(id, data) {const product = await Product.findByPk(id);if (!product) return false;// 更新数据库await product.update(data);// 更新缓存(或删除旧缓存)const cacheKey = `product:${id}`;await redisClient.setEx(cacheKey, 600, JSON.stringify(product.toJSON()));// 或删除缓存,下次查询时自动更新:await redisClient.del(cacheKey);return true;
}// 5. 测试
(async () => {await sequelize.sync();// 首次查询(数据库)console.log(await getProductById(1));// 二次查询(缓存)console.log(await getProductById(1));// 更新数据await updateProduct(1, { price: 99.9 });// 再次查询(更新后的缓存)console.log(await getProductById(1));// 关闭连接await redisClient.disconnect();await sequelize.close();
})();
缓存策略关键点
  1. 缓存键设计:使用前缀区分类型(如 product:1user:2),避免键冲突。
  2. 过期时间:设置合理的 TTL(生存时间),防止缓存数据长期过期(如商品信息10分钟过期)。
  3. 缓存更新
    • 写透模式:更新数据库后同步更新缓存。
    • 失效模式:更新数据库后删除缓存,下次查询时重建。
  4. 缓存穿透防护:对不存在的键设置短期空缓存,避免频繁查询数据库。
    // 缓存穿透防护
    if (!product) {await redisClient.setEx(cacheKey, 60, JSON.stringify(null)); // 空值缓存60秒return null;
    }
    
  5. 缓存雪崩防护:过期时间加随机值,避免大量缓存同时失效。
    const randomTTL = 600 + Math.floor(Math.random() * 60); // 10-11分钟随机
    await redisClient.setEx(cacheKey, randomTTL, data);
    

80. 什么是ORM和OODM?它们的区别是什么?

ORM(Object-Relational Mapping,对象关系映射)OODM(Object-Oriented Data Model,面向对象数据模型) 是两种数据持久化技术,分别对应关系型数据库和面向对象数据库。

定义与核心作用
  • ORM

    • 作用:将关系型数据库的表、行映射为程序中的对象,通过操作对象实现对关系型数据库(如MySQL)的CRUD。
    • 解决问题:消除关系型数据模型与面向对象编程模型的差异(如表 vs 对象、外键 vs 关联)。
    • 示例:Sequelize、TypeORM。
  • OODM

    • 作用:直接将面向对象编程语言中的对象持久化到面向对象数据库(如db4o),保持对象的结构和关系。
    • 解决问题:避免关系型数据库存储复杂对象时的映射开销(如继承、多态)。
    • 示例:MongoDB的Mongoose(虽非严格OODM,但接近面向对象数据模型)。
区别对比
特性ORMOODM
目标数据库关系型数据库(MySQL、PostgreSQL)面向对象数据库(如db4o)或文档型数据库(MongoDB)
数据模型映射对象 → 表,属性 → 列,关联 → 外键对象直接持久化(保留类、继承、多态等特性)
处理关系复杂度复杂(需映射多表关联、JOIN操作)简单(对象引用直接对应内存中的关系)
适用场景结构化数据、强事务需求(如金融系统)复杂对象结构、频繁变更数据模型(如内容管理)
性能映射转换有一定开销无映射开销,性能更高(尤其复杂对象)
成熟度非常成熟(数十年历史)相对较新,生态不如ORM完善
总结
  • ORM 是关系型数据库与面向对象编程的桥梁,适合需要事务和结构化数据的场景。
  • OODM 更贴近面向对象编程模型,适合存储复杂对象和非结构化数据。
  • 实际开发中,ORM 应用更广泛(因关系型数据库普及),而 OODM 常与 NoSQL 数据库结合使用。

二、120道Node.js面试题目录列表

文章序号Node.js面试题120道
1Node.js面试题及详细答案120道(01-15)
2Node.js面试题及详细答案120道(16-30)
3Node.js面试题及详细答案120道(31-42)
4Node.js面试题及详细答案120道(43-55)
5Node.js面试题及详细答案120道(56-68)
6Node.js面试题及详细答案120道(69-80)
7Node.js面试题及详细答案120道(81-92)
8Node.js面试题及详细答案120道(93-100)
9Node.js面试题及详细答案120道(101-110)
10Node.js面试题及详细答案120道(111-120)
http://www.dtcms.com/a/420257.html

相关文章:

  • 如何做好网站需求分析wordpress 去除新闻
  • 申请完域名怎么做网站宁波怎么建网站模板
  • nancy网站开发网站排名推广推荐
  • 网站建设辶金手指排名十五北京工程设计公司排名
  • 安装php网站360全景图合成软件
  • 小学微机作业做网站wordpress随机
  • 二叉树第一周总结
  • 湖北商城网站建设多少钱用手机可以做网站吗
  • 惠州微网站建设网站建设公司位置
  • 个人网站可以做百度推广吗wordpress后台多媒体不显示缩
  • istio 部署
  • 专业做营销网站哪个平台查企业免费
  • 【故障】win7命令行窗口cmd闪退
  • 优化网站加载速度宿迁市建设局网站维修基金
  • Spring IOC源码篇六 核心方法obtainFreshBeanFactory.parseCustomElement
  • 【c++】红黑树的部分实现
  • cpp02:类和对象
  • 即墨城乡建设局网站金融网站建设报价方案
  • 公司网站建设的建议电商网站建设期末考试
  • 自己的做网站cms资源
  • 图像采集卡:连接镜头与机器的“视觉神经”,释放工业智能核心动力
  • 北京移动端网站多少钱wordpress 首页跳转
  • 大连网站平台研发创客贴做网站吗
  • 如何撤销网站备案注册公司材料怎么准备
  • 学生可做的网站主题微信公众上传wordpress
  • 延吉建设局网站wordpress门户加商城
  • 高并发系统的高可用架构
  • 怎么自己开一个网站当当网网站开发计划和预算
  • 网站建设可行性报告范文网站建设 投资合作
  • 惠城网站建设有哪些做财经类新闻的网站