2011-02-14 144 views
1

我需要按照從出生日期開始的年數範圍進行分組。這是我迄今爲止所做的。如果您使用500000條記錄運行存儲過程,然後查詢我寫的內容,則會看到大約需要25秒。我該如何改進它?mysql - 按年份範圍劃分的組

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

如果`EXPLAIN`表示它正在進行大量線性掃描,則可以通過索引`dob`列開始。 – Blrfl 2011-02-14 18:11:00

+0

感謝您的回覆。我忘了說我已經添加了dob字段的索引。你好,Marc。 – 2011-02-14 18:29:12

回答

1

你的 '年齡' 功能可以更高效。而不是強制mysql將日期轉換爲字符串,做子串,比較它們,然後將其轉換爲最終減法的數字,(year(now()) - year(dob)) - (dayofyear(now()) < dayofyear(dob))怎麼樣 - 保持它的全部數字並消除至少一層轉換。

同樣,由於它使用本機日期/時間函數,因此它增加了MySQL可以使用dob列上的索引的機會。由於您在查詢時從日期字段中動態獲取文本值,因此您的當前方法無法用索引處理。