我需要按出生日期的年份分组。这就是我到目前为止所做的。如果您使用500000条记录运行存储过程,然后我写的查询您将看到大约需要25秒。我该如何改进呢?
create table people(
id int not null auto_increment primary key,
`dob` date
);
delimiter //
drop procedure if exists date_random //
create procedure date_random(in low date,in upp date,in number int)
begin
declare i int default 0;
while i < number do
begin
insert into people (`dob`) values ( low + interval rand()* datediff(upp,low) day );
set i = i + 1;
end;
end while;
end //
delimiter ;
call date_random('1910-01-01',curdate(),500000);
delimiter //
create function `age`(dob date) returns int(11)
no sql
begin
return (year(curdate())-year(dob))-(right(curdate(),5)< right(dob,5) );
end //
delimiter ;
explain select sql_no_cache
concat_ws('-',min(age(dob)),max(age(dob))) as years,
count(*) as total
from people
group by if(age(dob)=0,1,ceil(age(dob)/5))
这是解释
的输出+----+-------------+--------+-------+---------------+------+---------+------+--------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------+-------+---------------+------+---------+------+--------+----------------------------------------------+
| 1 | SIMPLE | people | index | NULL | ip | 4 | NULL | 500000 | Using index; Using temporary; Using filesort |
+----+-------------+--------+-------+---------------+------+---------+------+--------+----------------------------------------------+
1 row in set (0.00 sec)
答案 0 :(得分:1)
您的'年龄'功能可能更有效。而不是强制mysql将日期转换为字符串,做子串,比较它们,然后转换为最后一个减法的数字,(year(now()) - year(dob)) - (dayofyear(now()) < dayofyear(dob))
怎么样 - 保持全部数字并消除至少一层铸造。
同样,由于它使用本机日期/时间函数,因此增加了MySQL在dob
列上使用索引的可能性。您的当前方法无法使用索引处理,因为您在查询时动态地从日期字段派生文本值。