水平分表以后怎么确定这个数据在哪一张表里面?

取模法

这是较为常用的方式。以MySQL为例,若按用户ID进行水平分表,假设要将数据存储在N个表中,可使用公式 table_id = user_id % N 来确定表的索引。其中 user_id 是用户的ID,table_id 是表的索引。比如有4个表 user_0user_1user_2user_3 ,当插入或查询数据时,都先通过此公式计算出 table_id ,进而明确操作的表。如插入数据时,示例代码如下:

DELIMITER $$
CREATE PROCEDURE insert_user(IN user_id INT, IN user_name VARCHAR(50))
BEGIN
    SET @table_id = MOD(user_id, 4);
    SET @query = CONCAT('INSERT INTO user_', @table_id, ' (id, name) VALUES (', user_id, ', "', user_name, '");');
    PREPARE stmt FROM @query;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
END $$
DELIMITER ;

查询数据时:

DELIMITER $$
CREATE PROCEDURE get_user(IN user_id INT)
BEGIN
    SET @table_id = MOD(user_id, 4);
    SET @query = CONCAT('SELECT * FROM user_', @table_id, ' WHERE id = ', user_id, ';');
    PREPARE stmt FROM @query;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
END $$
DELIMITER ;

范围法

预先设定好每个表的数据范围。例如,按照时间范围分表,将每月的数据存到不同表中。表 orders_202501 存储2025年1月的订单数据,表 orders_202502 存储2025年2月的订单数据等。插入或查询时,依据数据的时间字段判断所属表。比如查询2025年2月的订单,SQL语句为 SELECT * FROM orders_202502 WHERE order_time >= '2025 - 02 - 01 00:00:00' AND order_time < '2025 - 03 - 01 00:00:00'

映射表法

创建一张专门的映射表,用于记录数据主键与表名的对应关系。假设存在一个 user_mapping 表,结构为 (user_id, table_name) ,其中 user_id 是用户ID,table_name 是存储该用户数据的表名。插入数据时,先确定插入到哪个表,同时在 user_mapping 表中插入一条对应记录;查询时,先从 user_mapping 表中查出数据所在表名,再到对应表中查询具体数据。如查询用户ID为100的用户数据,先执行 SELECT table_name FROM user_mapping WHERE user_id = 100 得到表名,然后再从该表中查询数据。

你可能感兴趣的:(面试题,MySQL,数据库,java,MySQL)