03 Python 数据管理——《Python大数据实践(主编:吕欣 杨文川)》读书笔记

本文为《Python大数据实践(主编:吕欣 杨文川)》中“Python 数据管理”相关内容的读书笔记。本文主要从 Python 数据管理的实际应用角度出发,整理关系型数据库、非关系型数据库、事务处理、索引设计、数据读写、MongoDB 操作以及数据管理中的工程化思维。

本文不是对教材内容的简单复述,而是在学习基础上结合个人理解进行整理和扩展。


一、学习本章的整体认识

在学习 Python 大数据实践时,很多人会更关注数据分析、机器学习、可视化或者爬虫等内容,但如果从完整的数据处理流程来看,数据管理其实是非常基础的一环。

数据从产生到发挥价值,通常要经过以下过程:

  1. 数据采集;
  2. 数据清洗;
  3. 数据存储;
  4. 数据查询;
  5. 数据分析;
  6. 数据展示;
  7. 数据应用。

其中,数据管理主要解决的是数据如何被存储、如何被查询、如何被更新以及如何保证安全和稳定的问题。

Python 本身并不是数据库,但 Python 可以连接多种数据库,并且可以将数据库中的数据读取出来进行处理,也可以把处理后的结果重新写入数据库。因此,Python 在数据管理中的作用更像是一个桥梁。

它连接了数据源、数据库、数据处理程序和业务应用。


二、我对 Python 数据管理的理解

我认为,Python 数据管理并不是简单地会写几句 SQL,也不是只会连接 MySQL 或 MongoDB。

真正的数据管理能力至少包括三个层次:

第一层是操作能力。
也就是能够使用 Python 连接数据库,完成数据的增加、删除、修改和查询。

第二层是设计能力。
也就是能够根据数据特点设计合理的数据表结构、字段类型、索引方式和文档结构。

第三层是工程能力。
也就是能够考虑事务、异常处理、性能优化、安全风险、数据备份和系统扩展等问题。

如果只是写一段程序把数据存入数据库,这只能算是“能用”。
如果能让数据长期稳定、高效、安全地被使用,才算真正掌握了数据管理。


三、数据管理的核心任务

数据管理的核心不是单纯“存数据”,而是让数据在需要的时候能够被正确、高效地使用。

具体来说,数据管理需要解决以下几个问题:

  1. 数据应该存在哪里;
  2. 数据应该以什么结构存储;
  3. 数据如何保证不丢失;
  4. 数据如何保证一致性;
  5. 数据如何被快速查询;
  6. 数据如何被安全访问;
  7. 数据量变大后如何扩展;
  8. 数据出错后如何恢复。

因此,数据管理既涉及数据库技术,也涉及程序设计思想和系统架构思想。


四、关系型数据库的基本概念

关系型数据库是最常见的数据管理方式之一。它使用二维表来组织数据,数据以行和列的形式存储。

常见的关系型数据库包括:

  • MySQL;
  • PostgreSQL;
  • SQLite;
  • Oracle;
  • SQL Server。

关系型数据库适合存储结构清晰、关系明确的数据,例如用户信息、订单信息、商品信息、学生成绩、财务记录等。

例如,一个用户表可以设计为:

CREATE TABLE users (
    user_id INT PRIMARY KEY,
    username VARCHAR(50),
    phone VARCHAR(20),
    email VARCHAR(100),
    register_time DATETIME
);

在这个表中,每一行代表一个用户,每一列代表用户的某个属性。


五、关系型数据库的优点和局限

关系型数据库的优点主要包括:

  1. 数据结构清晰;
  2. 支持 SQL 查询;
  3. 支持事务;
  4. 数据一致性较强;
  5. 适合复杂关联查询;
  6. 适合管理结构化数据。

但是,关系型数据库也有一定局限:

  1. 表结构相对固定;
  2. 字段变更成本较高;
  3. 对非结构化数据支持不够灵活;
  4. 数据量极大时扩展成本较高;
  5. 高并发场景下需要额外优化。

因此,在实际项目中,并不是所有数据都适合放入关系型数据库。对于结构灵活、变化频繁或规模极大的数据,可以考虑非关系型数据库。


六、Python 连接 MySQL 数据库

Python 可以通过 pymysql 连接 MySQL 数据库。

示例代码如下:

import pymysql

conn = pymysql.connect(
    host="localhost",
    user="root",
    password="password",
    database="test",
    charset="utf8mb4"
)

cursor = conn.cursor()

sql = "SELECT * FROM users"

cursor.execute(sql)

result = cursor.fetchall()

for row in result:
    print(row)

cursor.close()
conn.close()

这段代码完成了数据库连接、SQL 执行、结果读取和连接关闭的基本过程。

在实际开发中,数据库连接使用完成后一定要关闭,否则可能造成连接资源浪费。


七、Python 数据库操作的基本流程

使用 Python 操作关系型数据库时,一般包括以下步骤:

  1. 导入数据库连接库;
  2. 创建数据库连接;
  3. 创建游标对象;
  4. 编写 SQL 语句;
  5. 执行 SQL 语句;
  6. 获取执行结果;
  7. 提交事务或回滚事务;
  8. 关闭游标和连接。

可以将这个过程理解为 Python 与数据库之间的一次“对话”。

Python 负责发送 SQL 命令,数据库负责执行命令并返回结果。


八、使用 Python 插入数据

插入单条数据时,可以使用 execute() 方法。

import pymysql

conn = pymysql.connect(
    host="localhost",
    user="root",
    password="password",
    database="test",
    charset="utf8mb4"
)

cursor = conn.cursor()

sql = "INSERT INTO users(user_id, username, phone) VALUES(%s, %s, %s)"

cursor.execute(sql, (1, "Tom", "13800000000"))

conn.commit()

cursor.close()
conn.close()

这里使用 %s 作为占位符,而不是直接拼接字符串。这样可以降低 SQL 注入风险。


九、批量插入数据

如果需要一次性插入多条数据,使用 executemany() 方法更加高效。

sql = "INSERT INTO users(user_id, username, phone) VALUES(%s, %s, %s)"

data = [
    (1, "Tom", "13800000000"),
    (2, "Jerry", "13900000000"),
    (3, "Alice", "13700000000")
]

cursor.executemany(sql, data)

conn.commit()

批量插入可以减少程序与数据库之间的交互次数,在数据量较大时效率更高。

在实际项目中,如果数据量特别大,还可以分批写入,例如每 1000 条或 10000 条提交一次,避免一次性写入过多导致数据库压力过大。


十、数据更新和删除操作

更新数据可以使用 UPDATE 语句。

sql = "UPDATE users SET phone = %s WHERE user_id = %s"

cursor.execute(sql, ("13600000000", 1))

conn.commit()

删除数据可以使用 DELETE 语句。

sql = "DELETE FROM users WHERE user_id = %s"

cursor.execute(sql, (1,))

conn.commit()

需要注意的是,更新和删除操作会改变数据库中的原始数据,因此必须谨慎执行。

在实际开发中,删除数据之前最好先查询确认,或者使用逻辑删除方式。例如增加一个 is_deleted 字段,而不是真正删除记录。


十一、事务处理的重要性

事务是关系型数据库中非常重要的概念。

事务可以理解为一组数据库操作,这组操作要么全部成功,要么全部失败。

例如,在转账场景中,至少包括两个操作:

  1. A 账户余额减少;
  2. B 账户余额增加。

如果第一个操作成功,第二个操作失败,就会造成数据错误。因此,这两个操作必须被放在同一个事务中。

事务具有 ACID 特性:

特性 含义
原子性 事务中的操作要么全部成功,要么全部失败
一致性 事务执行前后数据库状态保持正确
隔离性 多个事务之间不会随意相互干扰
持久性 事务提交后结果会被永久保存

十二、Python 中的事务控制

Python 中可以通过 commit() 提交事务,通过 rollback() 回滚事务。

try:
    sql1 = "UPDATE account SET balance = balance - 100 WHERE user_id = 1"
    sql2 = "UPDATE account SET balance = balance + 100 WHERE user_id = 2"

    cursor.execute(sql1)
    cursor.execute(sql2)

    conn.commit()
    print("转账成功")

except Exception as e:
    conn.rollback()
    print("转账失败,事务已回滚")
    print(e)

这段代码体现了事务处理的基本思想:

如果所有 SQL 都执行成功,就提交事务;
如果中间出现错误,就回滚事务。

事务的意义不只是让代码更规范,更重要的是保证关键数据不会因为程序异常而出现不一致。


十三、使用 Pandas 读取数据库数据

在数据分析中,经常需要把数据库中的数据读取为 DataFrame。

可以使用 pandas.read_sql() 方法。

import pandas as pd
import pymysql

conn = pymysql.connect(
    host="localhost",
    user="root",
    password="password",
    database="test",
    charset="utf8mb4"
)

sql = "SELECT * FROM users"

df = pd.read_sql(sql, conn)

print(df.head())

conn.close()

读取为 DataFrame 后,就可以使用 Pandas 进行进一步的数据分析。

例如:

print(df.info())

print(df.describe())

print(df["username"].value_counts())

这体现了 Python 的优势:它不仅能连接数据库,还能继续完成数据清洗、统计分析和可视化。


十四、Pandas 分块读取大数据

如果数据库表中的数据量很大,不适合一次性全部读取到内存中。

此时可以使用 chunksize 参数进行分块读取。

sql = "SELECT * FROM large_table"

for chunk in pd.read_sql(sql, conn, chunksize=10000):
    print(chunk.shape)

这种方式每次只读取一部分数据,可以有效降低内存压力。

在大数据处理中,分块读取是一种非常实用的思想。它体现了一个原则:

数据量较小时,可以一次性处理;数据量较大时,应采用分批、分块、流式处理。


十五、数据库设计中的范式思想

关系型数据库设计中经常提到范式。范式的主要作用是减少数据冗余,提高数据一致性。

第一范式要求字段具有原子性。
例如,不应把手机号和邮箱同时存放在“联系方式”一个字段中,而应拆分为不同字段。

第二范式要求非主键字段完全依赖主键。
例如,在订单明细表中,商品名称应依赖商品编号,而不是只依赖订单编号。

第三范式要求消除传递依赖。
例如,员工表中不应直接存储部门地址,而应通过部门编号关联部门表。

范式设计可以让数据结构更加清晰,也可以减少重复数据。


十六、范式与反范式的平衡

虽然范式设计很重要,但实际项目中并不是范式越严格越好。

如果完全遵守范式,可能会导致查询时需要关联多张表,从而降低查询效率。

例如,订单详情页需要展示用户信息、商品信息、优惠信息和物流信息。如果所有信息都严格拆分到不同表中,查询时可能需要多表连接。

为了提高查询效率,有时会适当冗余部分字段。

例如,在订单表中保存商品名称快照:

CREATE TABLE order_items (
    order_id INT,
    product_id INT,
    product_name VARCHAR(100),
    price DECIMAL(10, 2),
    quantity INT
);

这里的 product_name 可能在商品表中已经存在,但订单表中保留它可以避免商品名称后续变化影响历史订单展示。

因此,我的理解是:

数据库设计不是机械追求范式,而是在数据一致性和查询效率之间寻找平衡。


十七、索引的作用

索引是数据库中提高查询效率的重要工具。

可以把索引理解为书籍目录。如果没有目录,查找某一章内容需要从头翻到尾;如果有目录,就可以快速定位。

例如,为手机号字段建立索引:

CREATE INDEX idx_user_phone ON users(phone);

当执行以下查询时,数据库可以利用索引快速查找:

SELECT * FROM users WHERE phone = '13800000000';

索引可以显著提高查询速度,尤其是在数据量较大的表中。


十八、索引并不是越多越好

索引虽然可以提高查询效率,但也会带来额外成本。

因为插入、更新和删除数据时,数据库不仅要修改表数据,还要维护索引结构。

因此,索引过多可能导致写入速度下降。

索引设计需要结合实际查询场景。

适合建立索引的字段包括:

  1. 经常作为查询条件的字段;
  2. 经常用于排序的字段;
  3. 经常用于分组的字段;
  4. 经常用于表连接的字段;
  5. 区分度较高的字段。

不适合建立索引的字段包括:

  1. 数据重复率很高的字段;
  2. 很少用于查询的字段;
  3. 频繁更新的字段;
  4. 数据量很小的表中的字段。

十九、复合索引的理解

复合索引是由多个字段组成的索引。

例如:

CREATE INDEX idx_city_age ON users(city, age);

这个索引适合以下查询:

SELECT * FROM users WHERE city = '北京' AND age > 18;

复合索引需要注意最左匹配原则。

对于索引 (city, age),如果查询条件中包含 city,索引通常更容易被使用;如果只查询 age,可能无法充分利用该复合索引。

因此,复合索引的字段顺序很重要。

一般来说,应该把更常用于查询、区分度较高的字段放在前面。


二十、SQL 注入与安全问题

在 Python 中操作数据库时,不能直接拼接用户输入。

错误示例:

username = input("请输入用户名:")

sql = "SELECT * FROM users WHERE username = '" + username + "'"

这种写法可能带来 SQL 注入风险。

更安全的方式是使用参数化查询:

username = input("请输入用户名:")

sql = "SELECT * FROM users WHERE username = %s"

cursor.execute(sql, (username,))

参数化查询可以让数据库把用户输入当作普通参数处理,而不是当作 SQL 语句的一部分执行。

这说明数据管理不仅要考虑功能,还要考虑安全。


二十一、ORM 的基本思想

ORM 的全称是 Object Relational Mapping,即对象关系映射。

它可以把数据库中的表映射为 Python 类,把表中的记录映射为 Python 对象。

使用 ORM 后,开发者可以用面向对象的方式操作数据库,而不必直接编写大量 SQL。

常见的 Python ORM 框架包括:

  • SQLAlchemy;
  • Django ORM;
  • Peewee。

SQLAlchemy 示例:

from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import declarative_base, sessionmaker

engine = create_engine("mysql+pymysql://root:password@localhost/test")

Base = declarative_base()

class User(Base):
    __tablename__ = "users"

    user_id = Column(Integer, primary_key=True)
    username = Column(String(50))
    phone = Column(String(20))

Session = sessionmaker(bind=engine)

session = Session()

user = User(user_id=1, username="Tom", phone="13800000000")

session.add(user)

session.commit()

ORM 的优点是开发效率高、代码结构清晰。
但 ORM 也有不足,如果不了解底层 SQL,可能会写出性能很差的查询。

所以,ORM 可以提高效率,但不能代替 SQL 基础。


二十二、非关系型数据库的基本认识

随着数据规模扩大和数据类型变复杂,非关系型数据库得到了广泛应用。

非关系型数据库通常不要求固定表结构,数据组织方式更加灵活。

常见的非关系型数据库类型包括:

类型 代表数据库 适用场景
键值数据库 Redis 缓存、计数器、验证码、会话管理
文档数据库 MongoDB JSON 数据、日志、内容管理
列族数据库 HBase 海量稀疏数据、分布式存储
图数据库 Neo4j 社交网络、知识图谱、关系分析

非关系型数据库并不是为了完全取代关系型数据库,而是用于解决关系型数据库不擅长的问题。


二十三、关系型数据库与非关系型数据库的区别

关系型数据库和非关系型数据库的区别可以从以下几个方面理解:

对比维度 关系型数据库 非关系型数据库
数据结构 表结构固定 结构灵活
查询方式 SQL API、类 JSON 查询等
事务支持 通常较强 不同数据库差异较大
扩展方式 垂直扩展、分库分表 更适合水平扩展
适合数据 结构化数据 半结构化、非结构化数据
典型场景 订单、支付、用户信息 缓存、日志、文档、画像

在实际应用中,两者经常组合使用。

例如:

  1. 用户信息存入 MySQL;
  2. 用户行为日志存入 MongoDB;
  3. 热点数据存入 Redis;
  4. 离线分析数据存入 Hive 或数据仓库。

这种组合使用方式比单独使用某一种数据库更加灵活。


二十四、MongoDB 的文档存储思想

MongoDB 是一种常见的文档型数据库。它使用类似 JSON 的 BSON 文档存储数据。

例如,一个用户及其订单可以存储为:

{
  "user_id": "U001",
  "username": "Tom",
  "age": 20,
  "orders": [
    {
      "order_id": "O1001",
      "amount": 299.0,
      "items": [
        {
          "product_id": "P001",
          "quantity": 2
        }
      ]
    }
  ]
}

这种文档结构非常适合表示层级关系明显的数据。

与关系型数据库相比,MongoDB 的字段更加灵活,不要求每条数据都具有完全相同的结构。

但是,灵活不代表可以随意设计。
如果文档结构设计不合理,后续查询和统计会变得很复杂。


二十五、Python 操作 MongoDB

Python 可以使用 pymongo 操作 MongoDB。

连接 MongoDB:

from pymongo import MongoClient

client = MongoClient("mongodb://localhost:27017/")

db = client["test_db"]

collection = db["users"]

插入一条数据:

user = {
    "user_id": "U001",
    "username": "Tom",
    "age": 20
}

collection.insert_one(user)

查询一条数据:

result = collection.find_one({"user_id": "U001"})

print(result)

插入多条数据:

users = [
    {"user_id": "U002", "username": "Jerry", "age": 22},
    {"user_id": "U003", "username": "Alice", "age": 21}
]

collection.insert_many(users)

条件查询:

results = collection.find({"age": {"$gte": 21}})

for item in results:
    print(item)

MongoDB 的查询方式比较灵活,也比较贴近 Python 字典的写法。


二十六、MongoDB 索引

MongoDB 中同样需要索引来提高查询效率。

例如,为 user_id 创建索引:

collection.create_index("user_id")

如果经常按照年龄查询,也可以为 age 字段创建索引:

collection.create_index("age")

索引可以提高查询速度,但同样会增加写入和更新成本。

因此,MongoDB 的索引设计也不能盲目增加,而应该结合查询频率和数据规模进行判断。


二十七、MongoDB 聚合分析

MongoDB 的聚合管道可以完成较复杂的数据统计分析。

例如,统计不同年龄的用户数量:

pipeline = [
    {
        "$group": {
            "_id": "$age",
            "count": {"$sum": 1}
        }
    },
    {
        "$sort": {
            "_id": 1
        }
    }
]

result = collection.aggregate(pipeline)

for item in result:
    print(item)

聚合管道可以理解为一个数据处理流程。

常见阶段包括:

阶段 作用
$match 筛选数据
$group 分组统计
$sort 排序
$project 选择或重命名字段
$limit 限制返回数量

这种处理方式和 Pandas 中的数据分析思想有一定相似性。

例如:

  • $match 类似条件筛选;
  • $group 类似 groupby()
  • $sort 类似 sort_values()
  • $project 类似字段选择。

二十八、Redis 的基本理解

Redis 是一种键值型非关系数据库,通常用于缓存、高速读写和临时数据存储。

Redis 的特点是读写速度快,支持多种数据结构。

常见数据结构包括:

  1. String;
  2. List;
  3. Hash;
  4. Set;
  5. Sorted Set。

Redis 常见应用场景包括:

  1. 缓存热点数据;
  2. 存储验证码;
  3. 记录登录状态;
  4. 实现排行榜;
  5. 实现计数器;
  6. 实现消息队列的部分功能。

例如,用户登录验证码可以暂时存入 Redis,并设置过期时间。

这样既能提高读取速度,也能避免长期保存无用数据。


二十九、数据一致性与可用性的权衡

在分布式数据管理中,经常会遇到一致性和可用性之间的权衡。

一致性强调不同节点上的数据应该保持一致。
可用性强调系统应该尽可能持续提供服务。
分区容错性强调系统在网络异常时仍能继续运行。

在实际业务中,不同场景对数据一致性的要求不同。

例如:

  • 支付、转账、库存扣减等场景必须重视一致性;
  • 浏览量、点赞数、推荐结果等场景可以接受短时间不一致;
  • 日志和行为数据更关注写入能力和后续分析能力。

所以,数据库选型不能只看技术本身,还要看业务需求。

我的理解是:

越接近资金、权限和库存的数据,越要重视一致性;越接近展示、推荐和统计的数据,越可以适当追求性能和可用性。


三十、Python 数据管理中的异常处理

数据库操作中一定要重视异常处理。

尤其是在执行写入、更新和删除操作时,如果程序中途报错,可能导致数据状态异常。

常见写法如下:

try:
    cursor.execute(sql)
    conn.commit()

except Exception as e:
    conn.rollback()
    print("数据库操作失败:", e)

finally:
    cursor.close()
    conn.close()

其中:

  • try 中执行数据库操作;
  • except 中处理异常并回滚;
  • finally 中关闭资源。

这种写法可以提高程序的稳定性。


三十一、数据库连接管理

如果每次查询都重新建立数据库连接,会增加系统开销。

在实际项目中,可以使用连接池来管理数据库连接。

连接池的思想是提前创建一定数量的数据库连接,程序需要时从连接池中获取,用完后再归还。

这样可以避免频繁创建和销毁连接,提高系统效率。

对于简单学习代码来说,可以手动打开和关闭连接。
对于长期运行的项目,则更推荐使用连接池。


三十二、数据备份与恢复

数据管理不能只关注日常读写,还需要考虑数据备份和恢复。

因为数据库可能会遇到以下问题:

  1. 人为误删数据;
  2. 程序错误写入;
  3. 服务器故障;
  4. 磁盘损坏;
  5. 系统升级失败;
  6. 网络攻击。

因此,重要数据必须定期备份。

备份方式可以包括:

  1. 全量备份;
  2. 增量备份;
  3. 日志备份;
  4. 异地备份;
  5. 自动定时备份。

数据备份的价值,只有在发生事故时才会体现出来。

所以,在数据管理中,备份不是可选项,而是必要环节。


三十三、数据质量管理

数据管理不仅要保证数据能存储,还要保证数据质量。

常见的数据质量问题包括:

  1. 缺失值;
  2. 重复值;
  3. 异常值;
  4. 格式不统一;
  5. 字段含义不清;
  6. 数据更新不及时;
  7. 数据来源不一致。

在 Python 中,可以使用 Pandas 对数据质量进行检查。

例如,检查缺失值:

print(df.isnull().sum())

检查重复值:

print(df.duplicated().sum())

删除重复值:

df = df.drop_duplicates()

填充缺失值:

df["age"] = df["age"].fillna(df["age"].mean())

数据质量管理是数据分析之前的重要步骤。
如果数据质量不好,后续模型和分析结果也会不可靠。


三十四、数据管理与数据分析的关系

数据管理和数据分析不是两个完全独立的环节。

数据管理决定了数据是否可靠、是否容易获取、是否方便分析。
数据分析则进一步从数据中提取规律和价值。

如果数据库设计混乱,数据字段含义不清,数据质量不稳定,那么数据分析会非常困难。

例如,在分析用户消费行为时,如果订单表中用户编号格式不统一,商品分类字段缺失严重,就会影响统计结果。

因此,好的数据分析依赖好的数据管理。


三十五、从数据表到数据资产

通过本章学习,我认识到,数据不应该只被看作一张张表,而应该被看作一种资产。

如果数据只是被随意存储,没有标准、没有说明、没有质量控制,那么它的价值很低。

如果数据被合理组织、清洗、标注和管理,就可以支持统计分析、业务决策、机器学习和智能应用。

因此,数据管理的最终目标不是“存起来”,而是“用起来”。


三十六、Python 数据管理的实践建议

结合本章内容,我认为 Python 数据管理实践中需要注意以下几点。

第一,数据库连接要及时关闭,避免资源浪费。

第二,SQL 查询要使用参数化方式,避免 SQL 注入风险。

第三,大规模数据读取时要分块处理,避免内存溢出。

第四,涉及多步写入时要使用事务,避免数据不一致。

第五,索引设计要结合查询场景,不能盲目建立索引。

第六,表结构设计要兼顾规范性和查询效率。

第七,非关系型数据库虽然灵活,但同样需要合理设计数据结构。

第八,数据写入和更新要做好异常处理和日志记录。

第九,重要数据要定期备份。

第十,数据管理要服务于后续分析和业务应用。


三十七、本章学习总结

本章围绕 Python 数据管理展开,使我认识到数据库操作是 Python 大数据实践中的重要基础。

关系型数据库适合存储结构清晰、一致性要求较高的数据。它强调表结构、SQL 查询、事务处理和数据规范性。

非关系型数据库更加灵活,适合处理结构复杂、字段变化频繁或规模较大的数据。MongoDB 适合文档型数据,Redis 适合缓存和高速访问场景。

在 Python 实践中,数据库通常会和 Pandas、PyMySQL、SQLAlchemy、PyMongo 等工具结合使用。Python 的优势在于能够把数据读取、清洗、转换、分析和写入过程连接起来,形成完整的数据处理流程。

本章给我的重要启发是:数据管理不是简单地学习数据库命令,而是要理解数据从产生到应用的完整过程。

在实际应用中,数据库选型和设计不能只看技术是否流行,而应该结合数据结构、业务需求、查询方式、一致性要求、性能需求和维护成本综合判断。


三十八、个人理解

我认为,Python 数据管理的重点不是“会不会操作数据库”,而是能不能建立数据工程思维。

以前我可能会认为,只要会写 SQL,能把数据查出来、存进去,就算掌握了数据库操作。但通过本章学习可以发现,真正的数据管理还要考虑很多问题。

例如:

  • 数据表结构是否合理;
  • 字段类型是否合适;
  • 查询是否高效;
  • 数据写入是否安全;
  • 出现异常时能否回滚;
  • 数据量变大后是否还能支撑;
  • 数据是否需要备份;
  • 数据质量是否能够保证;
  • 数据是否方便后续分析。

这些问题都说明,数据管理不是单纯的技术细节,而是一种系统性能力。

Python 在其中的价值,是把数据库、数据处理和数据分析连接起来。
它既可以操作 MySQL 这样的关系型数据库,也可以操作 MongoDB、Redis 这样的非关系型数据库,还可以借助 Pandas 对数据进行清洗和分析。

因此,学习 Python 数据管理时,不应该只停留在 API 调用层面,而应该进一步理解不同数据库背后的设计思想。

我的总结是:

数据管理的本质,是让数据在正确的位置、以合适的结构、被安全而高效地使用。

只有理解这一点,才能真正把 Python 用到数据管理和大数据实践中。


参考代码汇总

1. MySQL 数据库连接

import pymysql

conn = pymysql.connect(
    host="localhost",
    user="root",
    password="password",
    database="test",
    charset="utf8mb4"
)

cursor = conn.cursor()

cursor.close()
conn.close()

2. MySQL 查询数据

sql = "SELECT * FROM users"

cursor.execute(sql)

result = cursor.fetchall()

for row in result:
    print(row)

3. MySQL 插入单条数据

sql = "INSERT INTO users(user_id, username, phone) VALUES(%s, %s, %s)"

cursor.execute(sql, (1, "Tom", "13800000000"))

conn.commit()

4. MySQL 批量插入数据

sql = "INSERT INTO users(user_id, username, phone) VALUES(%s, %s, %s)"

data = [
    (1, "Tom", "13800000000"),
    (2, "Jerry", "13900000000"),
    (3, "Alice", "13700000000")
]

cursor.executemany(sql, data)

conn.commit()

5. MySQL 更新数据

sql = "UPDATE users SET phone = %s WHERE user_id = %s"

cursor.execute(sql, ("13600000000", 1))

conn.commit()

6. MySQL 删除数据

sql = "DELETE FROM users WHERE user_id = %s"

cursor.execute(sql, (1,))

conn.commit()

7. 事务处理

try:
    cursor.execute(sql1)
    cursor.execute(sql2)

    conn.commit()

except Exception as e:
    conn.rollback()
    print("事务执行失败:", e)

8. Pandas 读取数据库

import pandas as pd

sql = "SELECT * FROM users"

df = pd.read_sql(sql, conn)

print(df.head())

9. Pandas 分块读取数据

sql = "SELECT * FROM large_table"

for chunk in pd.read_sql(sql, conn, chunksize=10000):
    print(chunk.shape)

10. SQLAlchemy ORM 示例

from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import declarative_base, sessionmaker

engine = create_engine("mysql+pymysql://root:password@localhost/test")

Base = declarative_base()

class User(Base):
    __tablename__ = "users"

    user_id = Column(Integer, primary_key=True)
    username = Column(String(50))
    phone = Column(String(20))

Session = sessionmaker(bind=engine)

session = Session()

user = User(user_id=1, username="Tom", phone="13800000000")

session.add(user)

session.commit()

11. MongoDB 连接

from pymongo import MongoClient

client = MongoClient("mongodb://localhost:27017/")

db = client["test_db"]

collection = db["users"]

12. MongoDB 插入数据

user = {
    "user_id": "U001",
    "username": "Tom",
    "age": 20
}

collection.insert_one(user)

13. MongoDB 插入多条数据

users = [
    {"user_id": "U002", "username": "Jerry", "age": 22},
    {"user_id": "U003", "username": "Alice", "age": 21}
]

collection.insert_many(users)

14. MongoDB 查询数据

result = collection.find_one({"user_id": "U001"})

print(result)

15. MongoDB 条件查询

results = collection.find({"age": {"$gte": 21}})

for item in results:
    print(item)

16. MongoDB 创建索引

collection.create_index("user_id")

17. MongoDB 聚合分析

pipeline = [
    {
        "$group": {
            "_id": "$age",
            "count": {"$sum": 1}
        }
    },
    {
        "$sort": {
            "_id": 1
        }
    }
]

result = collection.aggregate(pipeline)

for item in result:
    print(item)

18. 检查缺失值

print(df.isnull().sum())

19. 检查重复值

print(df.duplicated().sum())

20. 删除重复值

df = df.drop_duplicates()

21. 填充缺失值

df["age"] = df["age"].fillna(df["age"].mean())

更多推荐