2011-12-10 61 views
2

我在我的數據庫中有幾個不同的表格,我正嘗試使用Sphinx來快速進行全文搜索。爲便於討論,假設感興趣的主要記錄是裝箱單,其中一個包含在訂單發貨時。我如何使用Sphinx在所有這些表中執行復雜的查詢而不完全非規範化數據庫?如何使用Sphinx來搜索大型JOIN表?

每個裝箱單列出了訂單號,發貨人,收貨人以及貨件附帶的每個箱子的跟蹤編號。單獨的表格包含有關訂單項目的信息。附加表格包含客戶地址信息。所以,訂單包含框和框包含項目。 (在此問題底部列出示例架構)。

我希望能夠查詢到獅身人面像回答這樣的問題:

  • 多少誰住在一個名爲「楓葉」街頭訂購貨品與描述「大」的人呢?
  • 哪些訂單包含單詞「藍色」在框描述或訂單項的描述?

要回答這些類型的問題,我需要參考幾個表。由於Sphinx沒有JOIN,因此一種選擇是對數據庫進行非規範化。使用視圖反規範化,以便每行代表一個訂單項 - 加上它的父框和訂單的所有數據,將導致數十億非常寬的行。所以我一直在爲每個表創建一個單獨的索引。但是這不允許我像SQL JOIN那樣跨表查詢。還有其他解決方案嗎?

示例數據庫

CREATE TABLE orders (
    id    integer PRIMARY KEY, 
    date_ordered  date, 
    customer_po  varchar 
); 
INSERT INTO orders VALUES (1, '2012-12-13', NULL); 
INSERT INTO orders VALUES (2, '2012-12-14', 'DF312442'); 

CREATE TABLE parties (
    id    integer PRIMARY KEY, 
    order_id   integer NOT NULL REFERENCES orders(id), 
    party_type  varchar, 
    company   varchar, 
    city    varchar, 
    state   char(2) 
); 
INSERT INTO parties VALUES (1, 1, 'shipper', 'ACME, Inc.', 'New York', 'NY'); 
INSERT INTO parties VALUES (2, 1, 'recipient', 'Wylie Coyote Corp.', 'Flagstaff', 'AZ'); 
INSERT INTO parties VALUES (3, 2, 'shipper', 'Cyberdyne', 'Las Vegas', 'NV'); 
-- Please disregard the fact that this design permits multiple shippers and multiple recipients 
-- per order. This is a vastly simplified version of the system I'm working on. 

CREATE TABLE boxes (
    id    integer PRIMARY KEY, 
    order_id   integer NOT NULL REFERENCES orders(id), 
    tracking_num  varchar NOT NULL, 
    description  varchar NOT NULL, 
); 
INSERT INTO boxes VALUES (1, 1, '1234567890', 'household goods'); 
INSERT INTO boxes VALUES (2, 1, '0987654321', 'kitchen appliances'); 
INSERT INTO boxes VALUES (3, 2, 'ABCDE12345', 'audio equipment'); 

CREATE TABLE box_contents (
    id    integer PRIMARY KEY, 
    order_id   integer NOT NULL REFERENCES orders(id), 
    box    integer NOT NULL REFERENCES boxes(id), 
    qty_units  integer, 
    description  varchar 
); 
INSERT INTO box_contents VALUES (1, 1, 1, 4, 'cookbook'); 
INSERT INTO box_contents VALUES (2, 1, 1, 2, 'baby bottle'); 
INSERT INTO box_contents VALUES (3, 1, 2, 1, 'television'); 
INSERT INTO box_contents VALUES (4, 2, 3, 2, 'lamp'); 

回答

4

你把在構建指數sql_query加入。這些表格保持標準化,但是在構建索引時您會非規範化。

它只是一個基本的例子,但你的查詢會像.. ..。

sql_query = SELECT o.id,customer_po,UNIX_TIMESTAMP(date_ordered) AS date_ordered, \ 
    GROUP_CONCAT(DISTINCT party_type) AS party_type, \ 
    GROUP_CONCAT(DISTINCT company) AS company, \ 
    GROUP_CONCAT(DISTINCT city) AS city, \ 
    GROUP_CONCAT(DISTINCT description) AS description \ 
    FROM orders o \ 
    INNER JOIN parties p ON (o.id = p.order_id) \ 
    INNER JOIN box_contents b ON (o.id = b.order_id) \ 
    GROUP BY o.id \ 
    ORDER BY NULL 

更新:或者可以使用sql_joined_field做同樣的,但要避免實際sql_query連接。獅身人面像然後爲你做加入過程

+0

感謝您的回覆。除非我讀錯了查詢,否則會爲每個盒子項目創建一行。正確?以這種方式非規範化DB是非常昂貴的,因爲它需要在14個不同的表(包含數百萬行的幾個表)上加入JOIN。 – jamieb

+1

每個訂單一行 - 由於羣組。是的,它很昂貴,但整個想法是你運行一次,然後針對預建索引運行大量查詢。複雜構建快速查詢的索引。 – barryhunter