什么是能够加入MySQL的合理数量的行和表?

Phi*_*oum 1 mysql sql geography join

我有一张表将地点映射到邮政编码.例如,纽约州有大约2000个邮政编码.我有另一个表将邮件映射到它发送到的邮政编码,但这个表有大约500万行.我想找到发送到纽约州的所有邮件,这看起来很简单,但查询速度令人难以置信.我甚至无法等待足够长的时间才能完成.问题是有500万行吗?我不禁想到,如今计算机上的500万不应该是这么大的数字......哦,一切都被编入索引.SQL只是不是设计用于处理如此大的连接?

更新:正如人们所问,我已经用表定义和我正在使用的查询更新了这个问题.

-- 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;
Run Code Online (Sandbox Code Playgroud)

更新2:好的,我撒了谎.使用正确的索引,上面的查询工作正常.问题实际上是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           | 
+----+-------------+-------+--------+--------------------------------------------------------+---------+---------+----------------------+---------+---------------------------------+
Run Code Online (Sandbox Code Playgroud)

Mar*_*ers 5

MySQL完全能够处理涉及500万行甚至更多行的连接.

你的问题可能是两件事之一:

  • 你错过了一个索引.
  • 您正在以优化程序无法使用最佳索引的方式编写查询,例如,如果您在连接条件中使用的索引列上没有可搜索的函数.

既然你声称"一切都已编入索引",我猜它是第二个.发布您的表信息和您的查询,我们应该能够帮助您解决它.

您还可以在查询上运行EXPLAIN以查看它正在使用哪些索引.