原理:
适当的数据类型可以优化存储空间,提高查询和处理效率。不同数据类型占用不同的存储空间,影响索引效率和内存使用。
例子:
假设有一个用户表(users):
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50),
age TINYINT UNSIGNED,
email VARCHAR(100),
registration_date DATE
);
在这个例子中:
id
使用 INT 类型,足够存储大量用户IDage
使用 TINYINT UNSIGNED,范围0-255,足够表示年龄registration_date
使用 DATE,只存储日期信息实践建议:
原理:
索引是一种数据结构,用于加速数据库的检索操作。它类似于书的目录,允许数据库快速定位到所需的数据,而无需扫描整个表。
例子:
继续使用上面的users表,假设经常按邮箱和注册日期查询用户:
CREATE INDEX idx_email ON users(email);
CREATE INDEX idx_registration_date ON users(registration_date);
实践建议:
原理:
数据库规范化是一种系统化的方法,用于组织数据以减少冗余和提高数据完整性。
例子:
考虑一个未规范化的订单表:
CREATE TABLE orders (
order_id INT PRIMARY KEY,
customer_name VARCHAR(100),
customer_email VARCHAR(100),
product_name VARCHAR(100),
product_price DECIMAL(10,2),
order_date DATE
);
规范化后可以拆分为:
CREATE TABLE customers (
customer_id INT PRIMARY KEY,
name VARCHAR(100),
email VARCHAR(100)
);
CREATE TABLE products (
product_id INT PRIMARY KEY,
name VARCHAR(100),
price DECIMAL(10,2)
);
CREATE TABLE orders (
order_id INT PRIMARY KEY,
customer_id INT,
product_id INT,
order_date DATE,
FOREIGN KEY (customer_id) REFERENCES customers(customer_id),
FOREIGN KEY (product_id) REFERENCES products(product_id)
);
实践建议:
原理:
分区允许将大表分割成更小的、更易管理的部分,每个分区可以独立存储和操作。
例子:
假设有一个大型日志表,可以按月分区:
CREATE TABLE logs (
id INT NOT NULL,
created_at DATE NOT NULL,
message TEXT
)
PARTITION BY RANGE (YEAR(created_at)) (
PARTITION p2021 VALUES LESS THAN (2022),
PARTITION p2022 VALUES LESS THAN (2023),
PARTITION p2023 VALUES LESS THAN (2024)
);
实践建议:
原理:
垂直分割将表中的列分到不同的表中,通常基于列的使用频率或大小。
例子:
将用户表拆分为基本信息表和详细信息表:
CREATE TABLE user_basic (
user_id INT PRIMARY KEY,
username VARCHAR(50),
email VARCHAR(100)
);
CREATE TABLE user_details (
user_id INT PRIMARY KEY,
address TEXT,
bio TEXT,
FOREIGN KEY (user_id) REFERENCES user_basic(user_id)
);
实践建议:
原理:
水平分割将表的行分配到不同的表或数据库中,通常基于某个列的值。
例子:
按用户ID范围分割用户表:
-- 在数据库1
CREATE TABLE users_1 (
id INT PRIMARY KEY,
name VARCHAR(50),
email VARCHAR(100)
) -- 存储ID 1-1000000的用户
-- 在数据库2
CREATE TABLE users_2 (
id INT PRIMARY KEY,
name VARCHAR(50),
email VARCHAR(100)
) -- 存储ID 1000001-2000000的用户
实践建议:
原理:
反规范化通过增加冗余数据来提高读取性能,牺牲了一些写入性能和数据一致性。
例子:
在订单表中冗余存储商品名称:
CREATE TABLE orders (
order_id INT PRIMARY KEY,
product_id INT,
product_name VARCHAR(100), -- 冗余字段
quantity INT,
order_date DATE,
FOREIGN KEY (product_id) REFERENCES products(product_id)
);
实践建议:
原理:
预计算是提前计算并存储复杂查询结果的技术,用空间换时间。
例子:
创建一个每日销售汇总表:
CREATE TABLE daily_sales_summary (
date DATE PRIMARY KEY,
total_sales DECIMAL(10,2),
order_count INT
);
-- 使用存储过程每日更新
DELIMITER //
CREATE PROCEDURE update_daily_sales()
BEGIN
INSERT INTO daily_sales_summary (date, total_sales, order_count)
SELECT DATE(order_date), SUM(total_amount), COUNT(*)
FROM orders
WHERE DATE(order_date) = CURDATE()
ON DUPLICATE KEY UPDATE
total_sales = VALUES(total_sales),
order_count = VALUES(order_count);
END //
DELIMITER ;
实践建议:
原理:
读写分离将读操作和写操作分配到不同的数据库实例,提高系统的并发处理能力。
例子:
使用MySQL主从复制实现读写分离:
[mysqld]
server-id = 1
log-bin = mysql-bin
[mysqld]
server-id = 2
relay-log = slave-relay-bin
CHANGE MASTER TO
MASTER_HOST='主库IP',
MASTER_USER='replication_user',
MASTER_PASSWORD='password',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=0;
START SLAVE;
实践建议:
原理:
分库分表是将数据分散到多个数据库或表中,突破单一数据库的性能限制。
例子:
使用一致性哈希进行用户数据分片:
public class ConsistentHash<T> {
private final int numberOfReplicas;
private final SortedMap<Integer, T> circle = new TreeMap<>();
public ConsistentHash(int numberOfReplicas, Collection<T> nodes) {
this.numberOfReplicas = numberOfReplicas;
for (T node : nodes) {
add(node);
}
}
public void add(T node) {
for (int i = 0; i < numberOfReplicas; i++) {
circle.put(hash(node.toString() + i), node);
}
}
public T get(Object key) {
if (circle.isEmpty()) {
return null;
}
int hash = hash(key);
if (!circle.containsKey(hash)) {
SortedMap<Integer, T> tailMap = circle.tailMap(hash);
hash = tailMap.isEmpty() ? circle.firstKey() : tailMap.firstKey();
}
return circle.get(hash);
}
private int hash(Object key) {
return key.hashCode() & 0x7FFFFFFF;
}
}
实践建议: