วันอังคาร, มีนาคม 10, 2552

Best way to query

การหาข้อมูลจำนวนมากช่างยากเสียจริงๆ วันนี้ผมเจอข้อมูลขนาด 9X0,000 Record เลยสับสนว่าควรออกแบบ query และ table แบบไหนดี ตอนนี้มีทางเลือกสำหรับ table อยู่สามแบบ


ข้อมูลจริงในตาราง foo จะมีขนาดประมาณ 9 แสน record ส่วนตาราง bars มีขนาดใหญ่กว่า foo สามเท่า ผมคิด query ได้ 5 แบบ รวมการ query ร่วมกับ ferret ด้วย
SELECT * from foos WHERE foos.id in ( 
  SELECT distince foos_bars.id 
  FROM foos_bars WHERE foos_bars.bar_id in [2,5,3]) 
แบบแรกใช้ sub query จาก table ตามหลักกระทรวงศึกษาธิการ
SELECT * from foos 
  JOIN foos_bars on foos.id = foos_bars.foo_id 
  WHERE foos_bars.id in [2,5,3] GROUP BY foos.id 
แบบที่สองก็ตรงตามหลัก แต่มันน่าจะช้ามากเมื่อเจอคำสั่ง
Group by SELECT * from foos 
  WHERE (bar LIKE '% ข %') 
  AND (bar LIKE '% จ %') 
  AND (bar LIKE '% ค %') 
แบบที่สาม ผมจะลองรวมสาม table มาเป็นอันเดียวแล้วค่อย query ลดการ join table และ group by
SELECT * from foos 
  WHERE (bar LIKE '%[2]%') 
  AND (bar LIKE '%[5]%') 
  AND (bar LIKE '%[3]%') 
แบบที่สี่ ผมทำคล้ายแบบที่สามแต่มีความเชื่อว่าตัวเลขจะเร็วกว่าตัวอักษร
ids = FoosBarsText.bar_search("ก","จ","ค") select * from foos_bars_text where bar in ids
สุดท้ายผมกะจะลองใช้ ferret มาร่วมในการ query ด้วย ถ้าจะเขียน model ของ FoosBarsText น่าจะเขียนประมาณนี้
include Ferret::Search 

class FoosBarsText < ActiveRecord::Base 

acts_as_ferret :fields=> ['bar'] 

def FoosBarsText.bar_search(search_inputs) 
  bq = Ferret::Search::BooleanQuery.new 
  search_inputs.each do |search_input| 
    bq.add_query(Ferret::Search::TermQuery.new(:bar, search_input) 
  end 
  filter = Ferret::Search::QueryFilter.new(bq) 
  @vobjects = Item.find_by_contents(search_text,
    :filter => filter, :sort => ["section", "sale_category"])  
  redirect_to :results 
  end 
end
สุดท้ายไม่รู้ว่าแบบไหนจะเร็วที่สุด ไว้ถ้าได้ทดลองจะนำมาเล่าให้ฟังนะครับ

blog comments powered by Disqus