php mysql如何分表

php mysql如何分表
最新回答
中国移不动

2020-09-09 23:58:42

在PHP+MySQL环境下实现分表,需结合分表策略与代码实现,以下是具体步骤和注意事项:

一、分表策略选择
  1. 垂直分表

    适用场景:表字段过多,高频访问字段与低频字段分离。

    示例:将用户表的user_info(姓名、邮箱)和user_order(订单数据)拆分为两张表,通过user_id关联。

    优点:减少单表宽度,提升查询效率。

  2. 水平分表

    适用场景:单表数据量过大(如千万级),按行拆分。

    示例:按用户ID哈希或时间范围拆分订单表:CREATE TABLE orders_2023 (...); -- 存储2023年数据CREATE TABLE orders_2024 (...); -- 存储2024年数据

    优点:分散数据压力,支持并行查询。

  3. 复合分表

    适用场景:需同时优化字段和行数。

    示例:按用户ID哈希分表后,每张表再按年份垂直拆分。

二、PHP+MySQL分表实现步骤1. 创建新表// 示例:按年份水平分表$years = [2023, 2024];foreach ($years as $year) { $tableName = "orders_{$year}"; $sql = "CREATE TABLE IF NOT EXISTS {$tableName} ( id INT AUTO_INCREMENT PRIMARY KEY, user_id INT NOT NULL, amount DECIMAL(10,2), created_at DATETIME, INDEX (user_id) )"; $pdo->exec($sql);}2. 修改旧表(可选)

若需保留旧表作为入口,可添加分表标识字段:

ALTER TABLE orders ADD COLUMN is_migrated TINYINT DEFAULT 0;3. 写入数据

根据分表规则路由数据:

function insertOrder($userId, $amount, $date) { global $pdo; $year = date('Y', strtotime($date)); $tableName = "orders_{$year}"; $stmt = $pdo->prepare("INSERT INTO {$tableName} (user_id, amount, created_at) VALUES (?, ?, ?)"); $stmt->execute([$userId, $amount, $date]);}4. 查询数据
  • 单表查询:直接指定分表名。
  • 多表查询:使用UNION或应用层聚合:
function getUserOrders($userId) { global $pdo; $result = []; $tables = ["orders_2023", "orders_2024"]; foreach ($tables as $table) { $stmt = $pdo->prepare("SELECT * FROM {$table} WHERE user_id = ?"); $stmt->execute([$userId]); $result = array_merge($result, $stmt->fetchAll()); } return $result;}三、关键注意事项
  1. 避免锁冲突

    不同分表使用独立主键(如自增ID+表后缀),避免全局锁。

    示例:orders_2023_id_seq和orders_2024_id_seq。

  2. 数据一致性

    使用事务确保跨分表操作原子性:

    $pdo->beginTransaction();try { insertOrder($userId, 100, '2023-01-01'); insertOrder($userId, 200, '2024-01-01'); $pdo->commit();} catch (Exception $e) { $pdo->rollBack();}
  3. 灵活查询支持

    封装统一查询接口,隐藏分表逻辑:

    class OrderRepository { public function findByUser($userId) { // 自动路由到所有分表并合并结果 }}
  4. 定期清理数据

    删除历史分表前备份数据:

    $oldTable = "orders_2022";$pdo->exec("RENAME TABLE {$oldTable} TO {$oldTable}_archive");
四、分表优缺点权衡
  • 优点

    查询性能提升(单表数据量减少)。

    写入并发能力增强(锁粒度细化)。

  • 缺点

    跨分表JOIN复杂,需应用层处理。

    维护成本高(需管理多表结构)。

五、进阶建议
  • 使用中间件:如MyCat或ShardingSphere自动分片。
  • 动态表名:通过配置映射表名,避免硬编码。
  • 监控分表:跟踪各分表数据量,提前扩容。

通过合理选择分表策略并遵循上述实践,可显著提升PHP+MySQL应用的数据库性能。