如何解决如何优化在特定日期范围内搜索行的Mysql查询
|| 这是查询:select timespans.id as timespan_id,count(*) as num
from reports,timespans
where timespans.after_date >= \'2011-04-13 22:08:38\' and
timespans.after_date <= reports.authored_at and
reports.authored_at < timespans.before_date
group by timespans.id;
这是表defs:
创建表`reports`(
`id` int(11)NOT NULL auto_increment,
`source_id` int(11)默认为NULL,
url varchar(255)默认为NULL,
lat十进制(20,15)默认为NULL,
lng十进制(20,15)默认为NULL,
“内容”文本,
`注释`文本,
`authored_at`日期时间默认为NULL,
“ created_at”日期时间默认为NULL,
`updated_at`日期时间默认为NULL,
“数据”文本,
`title` varchar(255)默认为NULL,
`author_id` int(11)默认为NULL,
orig_id varchar(255)默认为NULL,
主键(`id`),
KEY`index_reports_on_title`(`title`),
KEY`index_content_on_reports`(`content`(128))
创建表`timespans`(
`id` int(11)NOT NULL auto_increment,
`after_date`日期时间默认为NULL,
`before_date`日期时间默认为NULL,
after_offset int(11)默认为NULL,
`before_offset` int(11)默认为NULL,
`is_common` tinyint(1)默认为NULL,
“ created_at”日期时间默认为NULL,
`updated_at`日期时间默认为NULL,
is_search_chunk tinyint(1)默认为NULL,
`is_day` tinyint(1)默认为NULL,
主键(`id`),
KEY`index_timespans_on_after_date`(`after_date`),
KEY`index_timespans_on_before_date`(`before_date`)
这是解释:
+ ---- + ------------- + ----------- + ------- + ---------- -------------------------------------------------- -+ ------------------------------- + --------- + ----- -+ -------- + --------------------------------------- ------- +
| id | select_type |桌子|类型可能的钥匙|关键key_len |参考|行|额外|
+ ---- + ------------- + ----------- + ------- + ---------- -------------------------------------------------- -+ ------------------------------- + --------- + ----- -+ -------- + --------------------------------------- ------- +
| 1 |简单时间跨度|范围| index_timespans_on_after_date,index_timespans_on_before_date | index_timespans_on_after_date | 9 | NULL | 84 |在哪里使用使用临时的;使用文件排序|
| 1 |简单报告|全部| NULL | NULL | NULL | NULL | 183297 |在哪里使用
+ ---- + ------------- + ----------- + ------- + ---------- -------------------------------------------------- -+ ------------------------------- + --------- + ----- -+ -------- + --------------------------------------- ------- +
这是我在authored_at上创建索引后的说明。如您所见,该索引实际上并没有被使用(我认为...)
+ ---- + ------------- + ----------- + ------- + ---------- -------------------------------------------------- -+ ------------------------------- + --------- + ----- -+ -------- + --------------------------------------- --------- +
| id | select_type |桌子|类型可能的钥匙|关键key_len |参考|行|额外|
+ ---- + ------------- + ----------- + ------- + ---------- -------------------------------------------------- -+ ------------------------------- + --------- + ----- -+ -------- + --------------------------------------- --------- +
| 1 |简单时间跨度|范围| index_timespans_on_after_date,index_timespans_on_before_date | index_timespans_on_after_date | 9 | NULL | 86 |在哪里使用使用临时的;使用文件排序|
| 1 |简单报告|全部| index_reports_on_authored_at | NULL | NULL | NULL | 183317 |检查每个记录的范围(索引图:0x8)|
+ ---- + ------------- + ----------- + ------- + ---------- -------------------------------------------------- -+ ------------------------------- + --------- + ----- -+ -------- + --------------------------------------- --------- +
报告表中大约有14.2万行,而时间跨度表中的行则少得多。
现在查询大约需要3秒钟。
奇怪的是,如果我在reports.authored_at上添加索引,实际上会使查询慢得多,大约20秒。我本以为这样做会相反,因为这样可以很容易地在范围的两端找到报告,然后将其余的扔掉,而不必检查所有报告。
有人可以澄清吗?我很沮丧。
解决方法
尝试将它们合并到单个多列索引中,而不是为时间跨度表创建两个单独的索引,而在单个索引中使用before_date和after_date。然后将该索引也添加到authored_at中。
,我这样重写您的查询:
select t.id,count(*) as num from timespans t
join reports r where t.after_date >= \'2011-04-13 22:08:38\'
and r.authored_at >= \'2011-04-13 22:08:38\'
and r.authored_at < t.before_date
group by t.id order by null;
并更改表的索引
alter table reports add index authored_at_idx(authored_at);
,您可以在第3列上使用数据库的分区功能。这将对您有很大帮助。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。