Skip to content

MariaDB 数据库与表

数据库管理

数据库概述

数据库是表的集合,用于组织和管理相关的数据。在MariaDB中,每个数据库都有自己的表、索引、视图和权限设置。

创建数据库

使用CREATE DATABASE语句创建数据库:

sql
CREATE DATABASE database_name;

或指定字符集和校对规则:

sql
CREATE DATABASE database_name
  CHARACTER SET utf8mb4
  COLLATE utf8mb4_unicode_ci;

查看数据库

使用以下命令查看所有数据库:

sql
SHOW DATABASES;

查看当前数据库:

sql
SELECT DATABASE();

选择数据库

使用USE语句选择要使用的数据库:

sql
USE database_name;

修改数据库

修改数据库的字符集和校对规则:

sql
ALTER DATABASE database_name
  CHARACTER SET utf8mb4
  COLLATE utf8mb4_unicode_ci;

删除数据库

使用DROP DATABASE语句删除数据库:

sql
DROP DATABASE database_name;

注意:删除数据库会永久删除所有包含的数据和对象,操作不可逆。

表设计与优化

表设计原则

  1. 遵循第三范式(3NF)

    • 表中的每一列都应该直接依赖于主键
    • 避免数据冗余
    • 提高数据一致性
  2. 选择合适的数据类型

    • 使用最小的数据类型存储数据
    • 优先使用整数类型存储数值
    • 使用VARCHAR代替CHAR存储可变长度字符串
    • 对日期和时间使用专用数据类型
  3. 设计合理的主键

    • 主键应该唯一标识表中的每一行
    • 优先使用整数类型作为主键
    • 考虑使用自增主键
    • 避免使用复合主键(除非必要)
  4. 设计适当的索引

    • 为经常查询的列创建索引
    • 为JOIN操作的连接列创建索引
    • 为WHERE子句中频繁使用的列创建索引
    • 避免过度索引

数据类型选择

数值类型

数据类型存储大小范围适用场景
TINYINT1字节-128 到 127小整数,如状态码、标志位
SMALLINT2字节-32768 到 32767中等整数,如数量、年龄
MEDIUMINT3字节-8388608 到 8388607较大整数,如ID
INT4字节-2147483648 到 2147483647常用整数,如ID、数量
BIGINT8字节-9223372036854775808 到 9223372036854775807极大整数,如大表ID、时间戳
DECIMAL(M,D)可变取决于M和D精确小数,如金额、价格
FLOAT4字节单精度浮点数近似小数,如科学计算
DOUBLE8字节双精度浮点数高精度近似小数

字符串类型

数据类型存储大小适用场景
CHAR(N)N字节固定长度字符串,如密码哈希
VARCHAR(N)可变,1-2字节前缀+实际长度可变长度字符串,如姓名、地址
TEXT可变,最大65,535字节长文本,如描述、内容
MEDIUMTEXT可变,最大16,777,215字节中等长度文本,如文章内容
LONGTEXT可变,最大4,294,967,295字节超长文本,如大型文档
BLOB可变,最大65,535字节二进制数据,如图片缩略图
MEDIUMBLOB可变,最大16,777,215字节中等二进制数据
LONGBLOB可变,最大4,294,967,295字节大型二进制数据,如视频文件

日期和时间类型

数据类型存储大小格式适用场景
DATE3字节YYYY-MM-DD日期,如生日、订单日期
TIME3字节HH:MM:SS时间,如事件时间、持续时间
DATETIME8字节YYYY-MM-DD HH:MM:SS日期和时间,如创建时间、更新时间
TIMESTAMP4字节YYYY-MM-DD HH:MM:SS时间戳,自动更新,如最后修改时间
YEAR1字节YYYY年份,如发布年份

创建表

使用CREATE TABLE语句创建表:

sql
CREATE TABLE users (
  id INT AUTO_INCREMENT PRIMARY KEY,
  username VARCHAR(50) NOT NULL UNIQUE,
  email VARCHAR(100) NOT NULL UNIQUE,
  password VARCHAR(255) NOT NULL,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  status TINYINT DEFAULT 1
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

查看表结构

使用以下命令查看表结构:

sql
DESCRIBE table_name;

或:

sql
SHOW CREATE TABLE table_name;

修改表结构

使用ALTER TABLE语句修改表结构:

添加列

sql
ALTER TABLE users ADD COLUMN age INT;

修改列

sql
ALTER TABLE users MODIFY COLUMN age TINYINT UNSIGNED;

删除列

sql
ALTER TABLE users DROP COLUMN age;

添加索引

sql
ALTER TABLE users ADD INDEX idx_status (status);

修改表名

sql
ALTER TABLE old_table_name RENAME TO new_table_name;

删除表

使用DROP TABLE语句删除表:

sql
DROP TABLE table_name;

复制表

复制表结构

sql
CREATE TABLE new_table LIKE old_table;

复制表结构和数据

sql
CREATE TABLE new_table SELECT * FROM old_table;

或:

sql
INSERT INTO new_table SELECT * FROM old_table;

表操作

插入数据

使用INSERT INTO语句插入数据:

插入单行

sql
INSERT INTO users (username, email, password) 
VALUES ('john_doe', 'john@example.com', 'password123');

插入多行

sql
INSERT INTO users (username, email, password) 
VALUES 
  ('john_doe', 'john@example.com', 'password123'),
  ('jane_smith', 'jane@example.com', 'password456'),
  ('bob_johnson', 'bob@example.com', 'password789');

从其他表插入

sql
INSERT INTO new_users (username, email) 
SELECT username, email FROM old_users WHERE status = 1;

查询数据

使用SELECT语句查询数据:

基本查询

sql
SELECT id, username, email FROM users;

条件查询

sql
SELECT * FROM users WHERE status = 1 AND created_at > '2023-01-01';

排序

sql
SELECT * FROM users ORDER BY created_at DESC;

分页

sql
SELECT * FROM users LIMIT 10 OFFSET 20;

聚合查询

sql
SELECT status, COUNT(*) as user_count FROM users GROUP BY status;

更新数据

使用UPDATE语句更新数据:

sql
UPDATE users SET status = 0 WHERE id = 1;

或更新多行:

sql
UPDATE users SET status = 0 WHERE last_login < '2023-01-01';

删除数据

使用DELETE语句删除数据:

sql
DELETE FROM users WHERE id = 1;

或删除多行:

sql
DELETE FROM users WHERE status = 0 AND created_at < '2023-01-01';

截断表

使用TRUNCATE TABLE语句删除表中所有数据:

sql
TRUNCATE TABLE users;

注意TRUNCATE TABLEDELETE更快,但会重置自增计数器,且不能回滚。

表优化

优化表

使用OPTIMIZE TABLE语句优化表:

sql
OPTIMIZE TABLE users;

作用

  • 回收未使用的空间
  • 优化数据文件和索引结构
  • 提高查询性能

检查表

使用CHECK TABLE语句检查表的完整性:

sql
CHECK TABLE users;

修复表

使用REPAIR TABLE语句修复损坏的表:

sql
REPAIR TABLE users;

注意:主要用于MyISAM和Aria存储引擎,InnoDB通常不需要修复。

分析表

使用ANALYZE TABLE语句更新表的统计信息:

sql
ANALYZE TABLE users;

作用

  • 更新表的统计信息
  • 帮助查询优化器生成更好的执行计划

分区表

分区表概述

分区表是将一个大表分成多个小表,每个分区存储表的一部分数据。分区表可以提高查询性能,便于管理和维护。

分区类型

范围分区

根据列值的范围进行分区:

sql
CREATE TABLE orders (
  id INT AUTO_INCREMENT,
  order_date DATE,
  total_amount DECIMAL(10,2),
  PRIMARY KEY (id, order_date)
) ENGINE=InnoDB
PARTITION BY RANGE (YEAR(order_date)) (
  PARTITION p2021 VALUES LESS THAN (2022),
  PARTITION p2022 VALUES LESS THAN (2023),
  PARTITION p2023 VALUES LESS THAN (2024),
  PARTITION p2024 VALUES LESS THAN MAXVALUE
);

列表分区

根据列值的列表进行分区:

sql
CREATE TABLE sales (
  id INT AUTO_INCREMENT,
  region VARCHAR(20),
  amount DECIMAL(10,2),
  PRIMARY KEY (id, region)
) ENGINE=InnoDB
PARTITION BY LIST COLUMNS (region) (
  PARTITION p_north VALUES IN ('North', 'Northeast'),
  PARTITION p_south VALUES IN ('South', 'Southeast'),
  PARTITION p_west VALUES IN ('West', 'Southwest'),
  PARTITION p_central VALUES IN ('Central', 'Midwest')
);

哈希分区

根据列值的哈希值进行分区:

sql
CREATE TABLE users (
  id INT AUTO_INCREMENT,
  username VARCHAR(50),
  PRIMARY KEY (id)
) ENGINE=InnoDB
PARTITION BY HASH (id) PARTITIONS 4;

键分区

根据主键或唯一键的哈希值进行分区:

sql
CREATE TABLE products (
  id INT AUTO_INCREMENT,
  name VARCHAR(100),
  PRIMARY KEY (id)
) ENGINE=InnoDB
PARTITION BY KEY () PARTITIONS 8;

分区表管理

查看分区

sql
SHOW CREATE TABLE orders;

或:

sql
SELECT * FROM information_schema.partitions 
WHERE table_schema = 'database_name' AND table_name = 'orders';

添加分区

sql
ALTER TABLE orders ADD PARTITION (
  PARTITION p2025 VALUES LESS THAN (2026)
);

删除分区

sql
ALTER TABLE orders DROP PARTITION p2021;

合并分区

sql
ALTER TABLE orders REORGANIZE PARTITION p2022, p2023 INTO (
  PARTITION p2022_2023 VALUES LESS THAN (2024)
);

常见问题

如何选择合适的数据类型?

  • 数值:使用最小的整数类型,精确小数使用DECIMAL
  • 字符串:可变长度使用VARCHAR,固定长度使用CHAR
  • 日期和时间:根据精度需求选择DATE、TIME、DATETIME或TIMESTAMP
  • 二进制数据:根据大小选择BLOB、MEDIUMBLOB或LONGBLOB

如何设计合理的主键?

  • 优先使用整数类型
  • 考虑使用自增主键
  • 避免使用复合主键(除非必要)
  • 主键应该稳定,不经常变化
  • 主键应该唯一标识表中的每一行

什么时候使用分区表?

  • 表大小超过10GB
  • 查询经常访问表的一部分数据
  • 需要快速删除历史数据
  • 需要提高查询性能
  • 需要更好的管理和维护

如何优化大表?

  • 使用分区表
  • 合理设计索引
  • 优化查询语句
  • 考虑分库分表
  • 定期清理无用数据
  • 使用合适的存储引擎

如何备份表?

  • 使用mysqldump命令备份表:mysqldump -u user -p database_name table_name > table_name.sql
  • 使用SELECT INTO OUTFILE导出表数据:SELECT * INTO OUTFILE '/path/to/file.csv' FROM table_name
  • 使用物理备份工具(如mariabackup)

最佳实践

  1. 合理设计表结构

    • 遵循第三范式
    • 选择合适的数据类型
    • 设计合理的主键和索引
  2. 优化插入性能

    • 使用批量插入
    • 关闭自动提交(对于大量插入)
    • 禁用外键检查(临时)
    • 禁用唯一性检查(临时)
  3. 优化查询性能

    • 只查询需要的列
    • 使用索引优化查询
    • 避免在WHERE子句中使用函数
    • 优化JOIN操作
  4. 定期维护表

    • 定期优化表
    • 更新表统计信息
    • 检查和修复表(如果需要)
    • 监控表大小和增长趋势
  5. 使用分区表

    • 对于大表,考虑使用分区表
    • 选择合适的分区类型
    • 定期管理分区
  6. 备份表数据

    • 定期备份表数据
    • 测试备份恢复
    • 存储备份在安全的位置
  7. 监控表性能

    • 监控慢查询
    • 分析查询执行计划
    • 监控表锁和等待
    • 监控表空间使用情况

结论

数据库和表是MariaDB的核心组件,合理设计和管理数据库和表对于提高数据库性能、可靠性和可维护性至关重要。通过选择合适的数据类型、设计合理的表结构、优化查询和定期维护,可以确保MariaDB在生产环境中稳定高效地运行。

了解MariaDB的数据库和表管理功能,掌握表设计和优化的最佳实践,是每个DBA和数据库开发者的必备技能。