2010-04-02 57 views
1

我有一张表将地点映射到邮政编码。例如,纽约州有大约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   | 
+----+-------------+-------+--------+--------------------------------------------------------+---------+---------+----------------------+---------+---------------------------------+ 
+2

请在确切的表格和索引定义以及缓慢的查询中添加更多的细节。 – 2010-04-02 21:28:50

+0

注意:要显示确切的表格和索引定义,您可以为每个相关表格“SHOW CREATE TABLE tablename”显示并在此处张贴。 – 2010-04-02 21:37:01

+0

正如人们所问,我已经用表格定义和我正在使用的查询更新了这个问题。 – 2010-04-05 13:41:20

回答

5

MySQL完全有能力处理涉及500万行甚至更多的连接。

你的问题可能是以下两种情况之一:

  • 你缺少一个索引。
  • 您正在以这样一种方式编写查询,即优化程序无法使用最佳索引,例如,如果您在连接条件的索引列上使用的函数不是sargable

既然你声称“一切都被编入索引”,我猜测它是第二个。发布您的表格信息和您的查询,我们应该能够帮助您解决问题。

您也可以在查询上运行EXPLAIN来查看它正在使用的索引。

+0

正如人们所问,我已经用表格定义和我正在使用的查询更新了这个问题。 – 2010-04-05 13:41:39

0

为了论证的缘故,您应该能够加入10个表格,其中最大的表格具有数百万及以上的行,并且您应该能够快速获得结果。

假设索引策略或查询操作或查询计划存在一些问题。

它本身与SQL无关;它可能与MySQL或您在MySQL中使用的特定存储引擎有关。

您是否知道SQL标准没有定义任何与索引相关的内容?你可能会认为与索引有关的任何东西都是非标准的,但'标准之外'可能是更好的方式来看待它。

+0

正如人们所问,我已经用表格定义和我正在使用的查询更新了这个问题。 – 2010-04-05 13:42:46

相关问题