2016-07-23 94 views
0

我在MYSQL兩個表,其中表2中包含的序列號範圍(唯一的)與17位(VARCHAR 17)和table1的快速搜索與限制包含串行值(相同的格式範圍) 例如:MYSQL - 結果在範圍

table 1: 
serial_id seial 
1   12345678123456799 

table 2: 
range id  date    start    end 
1    2012-01-01  12345678123456789 12345678123456999 
2    2012-01-01  12345678123457000 12345678123457099 
3    2012-01-01  12345678123457100 12345678123457199 

我想找到每個序列屬於可以使用的後援簡單的查詢範圍IDS是:

select * 
from table1,table2 
where table1.serial between table2.start and table2.end 

但我想優化它與以下事實跑得更快: 連續劇和範圍是獨特的,所以每個串行可能屬於,且只有一個範圍。所以當一個範圍包含序列時,沒有必要搜索其他範圍。 每個範圍的前11位數字是相同的。例如,一個範圍可以從12345678120000000到12345678129999999. 連續和範圍按日期排序,並且更有可能在早期日期中找到範圍。連續出版物約有600萬條記錄,範圍約爲100000條記錄。

更好的查詢任何想法?

+0

你能告訴我們你從這些表中真正的查詢嗎?我問這個問題是因爲你的查詢返回6m記錄,而且它在現實世界中是無用的。這將使我們能夠提供更好的答案。 –

+0

@ Msf-vpt:我的真實查詢寫在上面。我銷售了具有序列號的產品批次範圍。我的範圍是批量出售,我想在銷售批次中搜索使用的批次。此查詢後,我可以找到未使用的連續,從銷售到使用,更快的賣家,和更多的信息延遲。 – user3833757

+1

提供創建所有相關表格和的解釋結果表的語句。並且不要使用邪惡的'SELECT *'。 – Strawberry

回答

0

這對加速有點具有挑戰性。下面是我用的IP地址範圍使用的一種方法:

select t1.*, 
     (select t2.range_id 
     from table2 t2 
     where t2.start <= t.serial 
     order by t2.start desc 
     limit 1 
     ) as range_id 
from table1 t1; 

這可以在table2(start, range_id)採取指數的優勢。

注意:這不檢查範圍的結束。爲此,我會添加另一個連接。 。 。雖然這(不幸的)需要物化的子查詢:

select * 
from (select t1.*, 
      (select t2.range_id 
       from table2 t2 
       where t2.start <= t.serial 
       order by t2.start desc 
       limit 1 
      ) as range_id 
     from table1 t1 
    ) t1 left join 
    table2 t2 
    on t1.range_id = t2.range_id and t2.end >= t.serial; 

額外加入希望在table2(range_id, end)的索引。

+0

謝謝Gordon,但是serial可能會比一個開始多一個,而「limit 1」會選擇第一個。如果第一個範圍不包含序列,則結果將不正確。例如:第一和第二範圍5中的範圍(1-3,4-7,8-10)中的5大於開始。但第二個包含它。 – user3833757

+0

@ user3833757。 。 。子查詢中的'order by'應該是下降的(就像現在這樣)。 –

0

我想通過數據模型的一點點改變,會發生很大的性能提升。 通過向table1添加rangeid列作爲外鍵。

table 1: 
serial_id seial    rangeid 
1   12345678123456799 1 

然後寫下面的查詢:

select * 
from table1 join table2 using(rangeid); 

如果這種改變是不可能的,你可以像使用操作如下:

select * 
from table1 join table2 
on(table2.start like concat(left(table1.serial,12),'%')) 
where table1.serial between table2.start and table2.end; 

table2.start列必須被索引。

編輯: 並以最大可能的數目的數字「12」,根據串行場之間的關係,開始場增加。

+0

謝謝,第一個不能到達,因爲連續記錄沒有任何範圍信息記錄。第二個想法需要更多時間來爲我運行。 – user3833757

+0

@ user3833757,你能告訴我需要多少時間嗎? –

+0

@ user3833757將數字「12」增加到可能的最大數量。 –

相關問題