-- 随机字符串函数
CREATE DEFINER=`root`@`%` FUNCTION `rand_string`(n INT) RETURNS varchar(255) CHARSET utf8
BEGIN
DECLARE chars_str varchar(100) DEFAULT 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
DECLARE return_str varchar(255) DEFAULT '' ;
DECLARE i INT DEFAULT 0;
WHILE i < n DO
SET return_str = concat(return_str,substring(chars_str , FLOOR(1 + RAND()*62 ),1));
SET i = i +1;
END WHILE;
RETURN return_str;
END
-- 随机范围时间函数
CREATE DEFINER=`root`@`%` FUNCTION `rand_date`(`startDate` date,`endDate` date) RETURNS datetime
BEGIN
#Routine body goes here...
DECLARE sec INT DEFAULT 0;
DECLARE ret DATETIME;
SET sec = ABS(UNIX_TIMESTAMP(endDate) - UNIX_TIMESTAMP(startDate));
SET ret = DATE_ADD(startDate, INTERVAL FLOOR( 1+RAND ( ) * ( sec-1))SECOND);
RETURN ret;
END
-- 模拟订单存储过程
CREATE DEFINER=`root`@`%` PROCEDURE `mock_order`(IN `size` int UNSIGNED,IN `sd` date,IN `ed` date)
BEGIN
#Routine body goes here...
DECLARE i int UNSIGNED DEFAULT 1;
DECLARE randOrderName VARCHAR(10);
DECLARE randOrderTime DATETIME;
WHILE i<= size DO
SELECT rand_string(10) INTO randOrderName;
SELECT rand_date(sd,ed) INTO randOrderTime;
INSERT INTO tb_order(`item_name`,`item_price`,`item_state`,`create_time`,`time_year`,`time_month`,`time_day`)
VALUES(randOrderName,RAND()*100,ROUND(RAND()),UNIX_TIMESTAMP(randOrderTime),DATE_FORMAT(randOrderTime,'%Y'),DATE_FORMAT(randOrderTime,'%m'),DATE_FORMAT(randOrderTime,'%d'));
SET i = i+1;
END WHILE;
END
-- 执行存储过程
CALL mock_order(1200000,'2020-03-01','2020-12-31')
-- CALL mock_order(FLOOR(RAND() * 9999999),'2020-03-01','2020-12-31')
SELECTsum(item_price) as total
FROM
tb_order
WHERE
item_state = 1AND create_time BETWEENUNIX_TIMESTAMP( '2020-04-01 00:00:00' )
ANDUNIX_TIMESTAMP( '2020-04-30 23:59:59' )
> OK
> 时间: 5.901s
3. 根据月份统计订单状态
SELECTcount( * ) AScount,
item_state AS state
FROM
tb_order
WHERE
create_time BETWEENUNIX_TIMESTAMP( '2020-04-01 00:00:00' )
ANDUNIX_TIMESTAMP( '2020-04-30 23:59:59' )
GROUPBY
item_state
> OK
> 时间: 12.126s
时间慢的有点不可接受
4. 查询日订单
SELECT
*
FROM
tb_order
WHERE
create_time BETWEENUNIX_TIMESTAMP( '2020-04-01 00:00:00' )
ANDUNIX_TIMESTAMP( '2020-04-1 23:59:59' )
> OK
> 时间: 0.54s
5. 统计日订单总额
SELECTSUM(item_price) as total
FROM
tb_order
WHERE
create_time BETWEENUNIX_TIMESTAMP( '2020-04-01 00:00:00' )
ANDUNIX_TIMESTAMP( '2020-04-1 23:59:59' )
> OK
> 时间: 0.154s
6. 分页查询月订单
SELECT
*
FROM
tb_order
WHERE
create_time BETWEENUNIX_TIMESTAMP( '2020-04-01 00:00:00' )
ANDUNIX_TIMESTAMP( '2020-04-30 23:59:59' )
LIMIT10000,20
> OK
> 时间: 0.107s
时间拆分的形式
1. 统计月订单数量
SELECTcount(1)
FROM
tb_order
WHERE
item_state = 1AND time_year = '2020'and time_month = '04'
> OK
> 时间: 1.329s
2. 统计月订单总额
SELECTsum( item_price ) AS total
FROM
tb_order
WHERE
item_state = 1AND time_year = '2020'AND time_month = '04'
> OK
> 时间: 1.23s
3. 根据月份统计订单状态
SELECTcount( * ) AScount,
item_state AS state
FROM
tb_order
WHERE
time_year = '2020'AND time_month = '04'GROUPBY
item_state
> OK
> 时间: 1.429s
4. 查询日订单
SELECT
*
FROM
tb_order
WHERE
time_year = '2020'and time_month = '04'and time_day = '01'
> OK
> 时间: 0.663s
5. 统计日订单总额
SELECTSUM(item_price) as total
FROM
tb_order
WHERE
time_year = '2020'AND time_month = '04'AND time_day = '01'
> OK
> 时间: 0.091s
6. 分页查询月订单
SELECT
*
FROM
tb_order
WHERE
create_time BETWEENUNIX_TIMESTAMP( '2020-04-01 00:00:00' )
ANDUNIX_TIMESTAMP( '2020-04-30 23:59:59' )
LIMIT10000,20
> OK
> 时间: 0.107s
由于 根据 时间戳来查询的结果是按照时间戳索引排序的,因此是从小到大
而单纯的拆分查询并没有有序
因此 添加一个order by 来进行排序
SELECT
*
FROM
tb_order
WHERE
time_year = '2020'AND time_month = '04'ORDERBY
create_time
LIMIT10000,
20
> OK
> 时间: 1.599s
SELECT
partition_name part,
partition_expression expr,
partition_description descr,
table_rows
FROM
information_schema.PARTITIONS
WHERE
table_schema = SCHEMA ()
AND table_name = 'tb_order_2';
4. 统计月订单
SELECTcount( 1 )
FROM
tb_order_2
WHERE
item_state = 1AND create_time BETWEENUNIX_TIMESTAMP( '2020-04-01 00:00:00' )
ANDUNIX_TIMESTAMP( '2020-04-30 23:59:59' )
> OK
> 时间: 0.133s
可以看出时间相比之间查询时间戳快很多。explain一下
用了分区进行查询
5. 统计月订单总额
SELECTsum(item_price) as total
FROM
tb_order_2
WHERE
item_state = 1AND create_time BETWEENUNIX_TIMESTAMP( '2020-04-01 00:00:00' )
ANDUNIX_TIMESTAMP( '2020-04-30 23:59:59' )
> OK
> 时间: 0.526s
6. 根据月份统计订单状态
SELECTcount( * ) AScount,
item_state AS state
FROM
tb_order_2
WHERE
create_time BETWEENUNIX_TIMESTAMP( '2020-04-01 00:00:00' )
ANDUNIX_TIMESTAMP( '2020-04-30 23:59:59' )
GROUPBY
item_state
> OK
> 时间: 0.273s
7. 查询日订单
SELECT
*
FROM
tb_order_2
WHERE
create_time BETWEENUNIX_TIMESTAMP( '2020-04-01 00:00:00' )
ANDUNIX_TIMESTAMP( '2020-04-1 23:59:59' )
> OK
> 时间: 0.587s
全部查询的话 并 差距并不大
8. 统计日订单总额
SELECTSUM(item_price) as total
FROM
tb_order_2
WHERE
create_time BETWEENUNIX_TIMESTAMP( '2020-04-01 00:00:00' )
ANDUNIX_TIMESTAMP( '2020-04-1 23:59:59' )
> OK
> 时间: 0.068s
9. 分页查询月订单
SELECT
*
FROM
tb_order_2
WHERE
create_time BETWEENUNIX_TIMESTAMP( '2020-04-01 00:00:00' )
ANDUNIX_TIMESTAMP( '2020-04-30 23:59:59' )
LIMIT10000,20
> OK
> 时间: 0.073s
图表
测试类型
统计月订单数
统计月订单总额
根据月份统计订单状态
查询日订单
统计日订单总额
分页查询月订单
时间戳
6.348s
5.901s
12.126s
0.54s
0.154s
0.107s
时间拆分
1.329s
1.23s
1.429s
0.663s
0.091s
0.107s
分区
0.133s
0.526s
0.273s
0.587s
0.068s
0.073s
总结
总体看来,就时间查询来说,效率是表分区>时间拆分>时间戳,时间戳的表结构为int结构,因为之间看过其他文章有对比过效率 int > datetime > timestamp,因此我在这里设计表的时候就采用了int的形式。