每小时根据时间字段对MySQL表进行分区

时间:2016-10-23 14:48:28

标签: mysql

我有一个包含以下字段的表格。

  $(document).ready(function() {
        $("#reset").on("click", function() {
          $('#table').find('#time').each(function() {
            $(this).val($(this).attr("data-default"));
          });
        });

现在我想创建每小时分区。所以它将有24个分区。主要原因是我的应用程序每天创建一个日志表,在日志表中有大约36000000条记录。因此,使搜索速度更快我想每小时创建一个分区。除了分区之外还有任何优化技术吗?

主要使用日期/时间/用户字段搜索数据。

1 个答案:

答案 0 :(得分:1)

使用上述架构,由于分区的requirement,无法进行分区:

在分区表达式中用于分区的所有列 表必须是表可能具有的每个唯一键的一部分

假设该表具有以下架构:

CREATE TABLE IF NOT EXISTS table1(
  log_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP(),
  user varchar(100),
  PRIMARY KEY(log_date, user)
);

然后有两种按小时划分的方法:使用HASHRANGE

按哈希分区:

CREATE TABLE IF NOT EXISTS table1(
  log_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP(),
  user varchar(100),
  PRIMARY KEY(log_date, user)
)
PARTITION BY HASH ( HOUR(log_date) ) 
PARTITIONS 24;

按范围划分:

CREATE TABLE IF NOT EXISTS table1(
  log_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP(),
  user varchar(100),
  PRIMARY KEY(log_date, user)
)
PARTITION BY RANGE ( HOUR(LogDate) ) (
    PARTITION p0 VALUES LESS THAN ( 1 ),
    PARTITION p1 VALUES LESS THAN ( 2 ),
    PARTITION p2 VALUES LESS THAN ( 3 ),
    PARTITION p3 VALUES LESS THAN ( 4 ),
    PARTITION p4 VALUES LESS THAN ( 5 ),
    PARTITION p5 VALUES LESS THAN ( 6 ),
    PARTITION p6 VALUES LESS THAN ( 7 ),
    PARTITION p7 VALUES LESS THAN ( 8 ),
    PARTITION p8 VALUES LESS THAN ( 9 ),
    PARTITION p9 VALUES LESS THAN ( 10 ),
    PARTITION p10 VALUES LESS THAN ( 11 ),
    PARTITION p11 VALUES LESS THAN ( 12 ),
    PARTITION p12 VALUES LESS THAN ( 13 ),
    PARTITION p13 VALUES LESS THAN ( 14 ),
    PARTITION p14 VALUES LESS THAN ( 15 ),
    PARTITION p15 VALUES LESS THAN ( 16 ),
    PARTITION p16 VALUES LESS THAN ( 17 ),
    PARTITION p17 VALUES LESS THAN ( 18 ),
    PARTITION p18 VALUES LESS THAN ( 19 ),
    PARTITION p19 VALUES LESS THAN ( 20 ),
    PARTITION p20 VALUES LESS THAN ( 21 ),
    PARTITION p21 VALUES LESS THAN ( 22 ),
    PARTITION p22 VALUES LESS THAN ( 23 ),
    PARTITION p23 VALUES LESS THAN MAXVALUE
);

插入值时

INSERT INTO table1(log_date, user) VALUES
('2019-2-4 20:23:', 'user1'),
('2019-2-4 20:33:', 'user1'),
('2019-2-4 20:43:', 'user1'),
('2019-2-4 20:53:', 'user1'),
('2019-2-4 21:23:', 'user1'),
('2019-2-4 21:33:', 'user1');

然后您可以确保它会落入正确的分区:

SELECT * FROM table1 PARTITION(p20);
+---------------------+-------+
| log_date            | user  |
+---------------------+-------+
| 2019-02-04 20:23:00 | user1 |
| 2019-02-04 20:33:00 | user1 |
| 2019-02-04 20:43:00 | user1 |
| 2019-02-04 20:53:00 | user1 |
+---------------------+-------+

无论如何使用mysql 8.0.19进行测试,像这样的简单选择将扫描整个分区:

EXPLAIN SELECT * FROM table1 WHERE log_date BETWEEN '2019-02-04 20:00' AND '2019-02-04 20:59';
+----+-------------+--------+---------------------------------------------------------------------------------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
| id | select_type | table  | partitions                                                                            | type  | possible_keys | key     | key_len | ref  | rows | filtered | Extra                    |
+----+-------------+--------+---------------------------------------------------------------------------------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
|  1 | SIMPLE      | table1 | p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15,p16,p17,p18,p19,p20,p21,p22,p23 | range | PRIMARY       | PRIMARY | 5       | NULL |    4 |   100.00 | Using where; Using index |
+----+-------------+--------+---------------------------------------------------------------------------------------+-------+---------------+---------+---------+------+------+----------+--------------------------+

选择应该与运算符log_date = '2019-02-04 20:23'一起使用,或者必须在表名后附加partition(p0)来执行。