我有一张表将地点映射到邮政编码。例如,纽约州有大约2000个邮政编码。我还有另一张表将邮件映射到发送给它的邮政编码,但这张表有大约500万行。我想查找发送给纽约州的所有邮件,这似乎很简单,但查询速度非常慢。我一直无法等待足够长的时间才能完成。问题是有500万行吗?我忍不住想,现在500万不应该是电脑这么大的一个数字......哦,一切都被编入索引。 SQL是不是被设计来处理这样的大型连接?什么是合理数量的行和表能够加入MySQL?
更新:正如人们所问,我已经更新了这个问题的表格定义和我正在使用的查询。
-- Roughly 70,000 rows
CREATE TABLE `mail_zip` (
`mail_id` int(11) default NULL,
`zip` int(11) default NULL,
KEY `index_mail_zip_on_mail_id` (`mail_id`),
KEY `index_mail_zip_on_zip` (`zip`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
-- Roughly 5,000,000 rows
CREATE TABLE `geographies` (
`city_id` int(11) default NULL,
`postal_code` int(11) default NULL,
KEY `index_geographies_on_city_id` (`city_id`),
KEY `index_geographies_on_postal_code` (`postal_code`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
-- Query
select mz.mail_id from mail_zip mz join geographies g on mz.zip = g.postal_code where g.city_id = 36 limit 10;
更新2:好吧,我撒谎。使用适当的索引,上述查询工作正常。问题实际上是order by子句。查看下面两个几乎相同的查询:唯一的区别是“order by m.sent_on desc”,它为查询增加了额外的4分30秒!另外,使用解释,通过使用文件添加顺序,这必须是减慢速度。但是,sent_on被索引,所以为什么不使用索引?我不应该正确编制索引。
-- Roughly 350,000 rows
CREATE TABLE `mail` (
`id` int(11) NOT NULL auto_increment,
`sent_on` datetime default NULL,
`title` varchar(255) default NULL,
PRIMARY KEY (`id`),
KEY `index_mail_on_sent_on` (`sent_on`),
) ENGINE=InnoDB DEFAULT CHARSET=latin1
-- Runs in 0.19 seconds
-- Query
select distinct(m.id), m.title from mail m join mail_zip mz on mz.mail_id = m.id join geographies g on g.postal_code = mz.zip where g.city_id = 36 limit 10;
+----+-------------+-------+--------+--------------------------------------------------------+---------+---------+----------------------+---------+-----------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+--------------------------------------------------------+---------+---------+----------------------+---------+-----------------------+
| 1 | SIMPLE | mz | ALL | index_mail_zip_on_com_id,index_mail_zip_on_zip | NULL | NULL | NULL | 5260053 | Using temporary |
| 1 | SIMPLE | m | eq_ref | PRIMARY | PRIMARY | 4 | mz.com_id | 1 | |
| 1 | SIMPLE | g | ref | index_geographies_on_city_id,zip | zip | 5 | mz.zip | 1 | Using where; Distinct |
+----+-------------+-------+--------+--------------------------------------------------------+---------+---------+----------------------+---------+-----------------------+
-- Runs in 4 minutes and 30 seconds
-- Query
select distinct(m.id), m.title from mail m join mail_zip mz on mz.mail_id = m.id join geographies g on g.postal_code = mz.zip where g.city_id = 36 order by m.sent_on desc limit 10;
+----+-------------+-------+--------+--------------------------------------------------------+---------+---------+----------------------+---------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+--------------------------------------------------------+---------+---------+----------------------+---------+---------------------------------+
| 1 | SIMPLE | mz | ALL | index_mail_zip_on_com_id,index_mail_zip_on_zip | NULL | NULL | NULL | 5260053 | Using temporary; Using filesort |
| 1 | SIMPLE | m | eq_ref | PRIMARY | PRIMARY | 4 | mz.com_id | 1 | |
| 1 | SIMPLE | g | ref | index_geographies_on_city_id,zip | zip | 5 | mz.zip | 1 | Using where; Distinct |
+----+-------------+-------+--------+--------------------------------------------------------+---------+---------+----------------------+---------+---------------------------------+
请在确切的表格和索引定义以及缓慢的查询中添加更多的细节。 – 2010-04-02 21:28:50
注意:要显示确切的表格和索引定义,您可以为每个相关表格“SHOW CREATE TABLE tablename”显示并在此处张贴。 – 2010-04-02 21:37:01
正如人们所问,我已经用表格定义和我正在使用的查询更新了这个问题。 – 2010-04-05 13:41:20