2010-04-02 14 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

相關問題