C语言核心概念复习——数据库与多路IO

数据库与多路IO基础

一、数据库基础操作(增删改查)

1. 创建表

复制代码
CREATE TABLE student (
    id INT PRIMARY KEY,        -- 学号,主键
    name VARCHAR(50),          -- 姓名
    age INT,                  -- 年龄
    score FLOAT              -- 成绩
);

说明

  • CREATE TABLE:创建数据表的命令

  • INT:整数类型

  • VARCHAR(50):可变长字符串,最大50字符

  • FLOAT:浮点数类型

  • PRIMARY KEY:主键约束,值唯一且非空

2. 增加数据(增)

复制代码
-- 插入一条完整数据
INSERT INTO student VALUES (1, '张三', 18, 90.5);

-- 插入指定字段数据
INSERT INTO student (id, name, score) VALUES (2, '李四', 85.5);

关键字INSERT INTO - 向表中添加新数据

3. 查询数据(查)

复制代码
-- 查询所有字段
SELECT * FROM student;

-- 查询指定字段
SELECT name, score FROM student;

-- 带条件查询
SELECT * FROM student WHERE age > 18;

-- 排序查询
SELECT * FROM student ORDER BY score DESC;  -- DESC:降序,ASC:升序

关键字SELECT - 从表中查询数据

4. 修改数据(改)

复制代码
-- 修改满足条件的数据
UPDATE student SET score = 95 WHERE id = 1;

-- 修改多个字段
UPDATE student SET age = 19, score = 88 WHERE name = '张三';

关键字UPDATE - 修改表中的数据

5. 删除数据(删)

复制代码
-- 删除满足条件的数据
DELETE FROM student WHERE id = 2;

-- 删除所有数据
DELETE FROM student;

关键字DELETE - 从表中删除数据

二、数据库效率问题

1. 数据量增大带来的问题

复制代码
单表数据量过大 → 查询变慢 → 索引效率下降 → 整体性能降低

2. 存储策略:分表存

垂直分表

复制代码
原表:id, name, age, score, address, phone, email
        ↓
主表:id, name, age, score
扩展表:id, address, phone, email

特点:按列拆分,将不常用字段分离

水平分表

复制代码
原表:1-100万条数据
        ↓
表1:1-25万条
表2:25-50万条  
表3:50-75万条
表4:75-100万条

特点:按行拆分,将数据分散到多个结构相同的表

分表目的

  • 减少单表数据量

  • 提高查询速度

  • 降低锁竞争

  • 便于维护

三、多路IO技术

1. 什么是多路IO

定义:一个进程可以同时监听多个文件描述符,当某个文件描述符就绪(可读/可写)时,通知应用程序处理。

类比

复制代码
单路IO:一个服务员只服务一桌客人
多路IO:一个服务员同时服务多桌客人,哪桌有需要就服务哪桌

2. 三种多路IO模型对比

特性 select poll epoll
文件描述符限制 最多1024个 无限制 无限制
效率 中等
实现机制 轮询 轮询 回调
内存拷贝 每次都要从内核拷贝 每次都要从内核拷贝 共享内存

四、select详解

1. select特点

  • 最大限制:最多监听1024个文件描述符

  • 效率低:每次调用都需要遍历所有文件描述符

  • 工作原理:轮询方式,线性扫描

2. select工作流程

复制代码
1. 应用程序设置要监听的文件描述符集合
2. 调用select,进程阻塞
3. 内核遍历文件描述符集合
4. 有就绪事件返回
5. 应用程序再次遍历找到就绪的描述符
6. 处理数据

3. select代码示例

复制代码
fd_set readfds;
struct timeval tv;

FD_ZERO(&readfds);              // 清空集合
FD_SET(sockfd, &readfds);      // 添加socket到集合

tv.tv_sec = 5;                 // 超时时间5秒
tv.tv_usec = 0;

int ret = select(maxfd + 1, &readfds, NULL, NULL, &tv);

if (ret > 0) {
    if (FD_ISSET(sockfd, &readfds)) {  // 检查socket是否就绪
        // 处理数据
    }
}

select缺点

  1. 监听上限1024个文件描述符

  2. 每次调用都需要从用户空间拷贝集合到内核空间

  3. 返回后需要遍历所有描述符才能找到就绪的

五、poll详解

1. poll特点

  • 无限制:监听文件描述符数量没有上限

  • 效率中等:仍是轮询方式,但不需要拷贝整个集合

  • 数据结构:使用pollfd结构体数组

2. pollfd结构体

复制代码
struct pollfd {
    int fd;          // 文件描述符
    short events;    // 监听的事件(读/写/异常)
    short revents;   // 返回的就绪事件
};

3. poll工作流程

复制代码
1. 应用程序填充pollfd数组
2. 调用poll,进程阻塞
3. 内核遍历pollfd数组
4. 有就绪事件返回,设置revents
5. 应用程序遍历数组检查revents
6. 处理数据

4. poll代码示例

复制代码
struct pollfd fds[10];
fds[0].fd = sockfd;           // 设置文件描述符
fds[0].events = POLLIN;       // 监听读事件

int ret = poll(fds, 1, 5000); // 超时5秒

if (ret > 0) {
    if (fds[0].revents & POLLIN) {  // 检查读事件是否就绪
        // 处理数据
    }
}

poll优点

  • 无1024上限

  • 不需要重新初始化事件集合

poll缺点

  • 仍需要遍历所有描述符

  • 用户空间到内核空间的数组拷贝

六、epoll详解

1. epoll特点

  • 效率高:回调机制,只返回就绪的描述符

  • 无限制:监听数量没有上限

  • 内存共享:使用mmap共享内存,减少拷贝

2. epoll工作流程

复制代码
1. epoll_create() - 创建epoll实例
2. epoll_ctl()    - 添加/修改/删除监听的文件描述符
3. epoll_wait()   - 等待事件发生,返回就绪的描述符
4. 直接处理就绪的描述符(无需遍历所有)

3. epoll代码示例

复制代码
// 1. 创建epoll实例
int epfd = epoll_create(1);

// 2. 设置监听事件
struct epoll_event ev;
ev.events = EPOLLIN;          // 监听读事件
ev.data.fd = sockfd;          // 关联的文件描述符

epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &ev);  // 添加监听

// 3. 等待事件发生
struct epoll_event events[10];
int nfds = epoll_wait(epfd, events, 10, 5000);

// 4. 处理就绪事件
for (int i = 0; i < nfds; i++) {
    // events[i].data.fd 就是就绪的文件描述符
    // 直接处理,无需遍历
}

4. epoll两种工作模式

LT模式(水平触发)

复制代码
特点:只要缓冲区有数据,就会一直通知
默认模式,编程简单

ET模式(边缘触发)

复制代码
特点:只有状态发生变化时通知一次
效率更高,需要循环读取数据

七、三种多路IO对比总结

1. 效率对比

复制代码
select  <  poll  <  epoll
(最低)         (最高)

2. 适用场景

技术 适用场景 原因
select 监听少量连接(<1024) 实现简单,跨平台好
poll 监听较多连接 无数量限制,但仍有性能问题
epoll 高并发、海量连接 效率最高,只返回就绪事件

3. 核心区别

复制代码
select/poll:
   "有多少个连接?我全部查一遍"
   ↓
   遍历1000个,找到2个就绪
   ↓
   处理这2个

epoll:
   "哪个连接好了?告诉我"
   ↓
   直接返回2个就绪的连接
   ↓
   处理这2个

八、综合示例:数据库+多路IO

1. 典型应用场景

复制代码
客户端连接 → epoll监听 → 接收请求 → 查询数据库 → 返回结果

2. 流程示例

复制代码
// 1. 创建epoll监听客户端连接
epoll_wait(epfd, events, 10, -1);

// 2. 收到查询请求
recv(client_fd, query, sizeof(query), 0);
// 例如:SELECT * FROM student WHERE id = 1

// 3. 查询数据库
// 执行SQL语句,获取结果

// 4. 返回结果给客户端
send(client_fd, result, len, 0);

总结

  1. 数据库基础:增删改查是核心操作,通过SQL语句实现

  2. 分表存储:数据量大时的优化策略,提高查询效率

  3. 多路IO:单进程监听多个文件描述符的技术

  4. select/poll/epoll:三种实现方式,效率和机制各不相同

  5. epoll优势:在高并发场景下性能最好,是现代网络编程的首选

相关推荐
小高不会迪斯科9 小时前
CMU 15445学习心得(二) 内存管理及数据移动--数据库系统如何玩转内存
数据库·oracle
寻寻觅觅☆9 小时前
东华OJ-基础题-106-大整数相加(C++)
开发语言·c++·算法
YJlio9 小时前
1.7 通过 Sysinternals Live 在线运行工具:不下载也能用的“云端工具箱”
c语言·网络·python·数码相机·ios·django·iphone
e***89010 小时前
MySQL 8.0版本JDBC驱动Jar包
数据库·mysql·jar
l1t10 小时前
在wsl的python 3.14.3容器中使用databend包
开发语言·数据库·python·databend
小白同学_C10 小时前
Lab4-Lab: traps && MIT6.1810操作系统工程【持续更新】 _
linux·c/c++·操作系统os
今天只学一颗糖10 小时前
1、《深入理解计算机系统》--计算机系统介绍
linux·笔记·学习·系统架构
赶路人儿10 小时前
Jsoniter(java版本)使用介绍
java·开发语言
testpassportcn10 小时前
AWS DOP-C02 認證完整解析|AWS DevOps Engineer Professional 考試
网络·学习·改行学it
ceclar12311 小时前
C++使用format
开发语言·c++·算法