2012-08-07 71 views
0

我有一張擁有250萬名醫生名單的表格。我還提供了接受保險,所用語言和專業(分類學)的表格。醫生表是這樣的:使用各種其他信息對250萬個物品進行索引

CREATE TABLE `doctors` (
    `doctor_id` int(10) NOT NULL AUTO_INCREMENT, 
    `city_id` int(10) NOT NULL DEFAULT '0', 
    `d_gender` char(1) NOT NULL DEFAULT 'U', 
    `s_insurance` int(6) NOT NULL DEFAULT '0', 
    `s_languages` int(6) NOT NULL DEFAULT '0', 
    `s_taxonomy` int(6) NOT NULL DEFAULT '0', 
    PRIMARY KEY (`doctor_id`) 
) ENGINE=InnoDB; 

其他信息被存儲爲這樣:

CREATE TABLE `doctors_insurance` (
    `assoc_id` int(10) NOT NULL AUTO_INCREMENT, 
    `doctor_id` int(10) NOT NULL DEFAULT '0', 
    `insurance_id` int(10) NOT NULL DEFAULT '0', 
    PRIMARY KEY (`assoc_id`) 
) ENGINE=InnoDB; 

CREATE TABLE `doctors_languages` (
    `assoc_id` int(10) NOT NULL AUTO_INCREMENT, 
    `doctor_id` int(10) NOT NULL DEFAULT '0', 
    `language_id` int(10) NOT NULL DEFAULT '0', 
    PRIMARY KEY (`assoc_id`) 
) ENGINE=InnoDB; 

CREATE TABLE `doctors_taxonomy` (
    `assoc_id` int(10) NOT NULL AUTO_INCREMENT, 
    `doctor_id` int(10) NOT NULL DEFAULT '0', 
    `taxonomy_id` int(10) NOT NULL DEFAULT '0', 
    PRIMARY KEY (`assoc_id`) 
) ENGINE=InnoDB; 

當然每個醫生支持各種不同的保險計劃,也許會講多國語言,有的醫生可以有幾種不同的特色(分類)。所以我選擇了用於索引的單獨表格,這種方式需要添加新索引或刪除舊索引,我可以簡單地刪除這些表格,而不必等待很長時間才能以舊式的方式實現。

也因爲其他縮放技術在未來考慮,經典JOIN對我現在沒有什麼影響,所以我並不擔心它。

索引的名字很簡單:

CREATE TABLE `indices_doctors_names` (
    `ref_id` int(10) NOT NULL AUTO_INCREMENT, 
    `doctor_id` int(10) NOT NULL DEFAULT '0', 
    `practice_id` int(10) NOT NULL DEFAULT '0', 
    `name` varchar(120) NOT NULL DEFAULT '', 
    PRIMARY KEY (`ref_id`), 
    KEY `name` (`name`) 
) ENGINE=InnoDB; 

然而,當我想要讓人們在城市,特色菜,保險,語言,性別和其他人口統計數據進行搜索,我創造了他:

CREATE TABLE `indices_doctors_demos` (
    `ref_id` int(10) NOT NULL AUTO_INCREMENT, 
    `doctor_id` int(10) NOT NULL DEFAULT '0', 
    `city_id` int(10) NOT NULL DEFAULT '0', 
    `taxonomy_id` int(6) NOT NULL DEFAULT '0', 
    `insurance_id` int(6) NOT NULL DEFAULT '0', 
    `language_id` int(6) NOT NULL DEFAULT '0', 
    `gender_id` char(1) NOT NULL DEFAULT 'U', 
    PRIMARY KEY (`ref_id`), 
    KEY `index` (`city_id`,`taxonomy_id`,`insurance_id`,`language_id`,`gender_id`) 
) ENGINE=InnoDB; 

這個想法是,主要針對專業,保險或語言的每個變化都會有一個條目,儘管其他條目仍然是一樣的。這造成了一個明顯的問題。如果醫生有3個專業,支持3個保險提供者,並且會講3種語言,則僅此一項就意味着這位特定的醫生有27個條目。因此,250萬條條目容易形成更多。

必須有更好的方法來做到這一點,但它怎麼做呢?再一次,我對轉向傳統索引技術和使用JOIN不感興趣,因爲它會很快變得太慢,我需要一種可以輕鬆擴展的方法。

回答

0

我知道這不是你要找的答案,但你現在已經把RDBMs做得很好的事情,並嘗試自己實現它,使用RDBM可以用來實際理解的相同機制您的數據並優化檢索和查詢。在實踐中,你已經決定放棄使用適當的索引來創建你自己的中途解決方案,它將嘗試自己實現索引(通過使用KEY實際使用RDBM的索引功能)。

我建議實際嘗試按照您已經構建它的方式來使用數據庫。 2.5m行不是那麼多行,並且您應該能夠使用JOIN和索引使其在您的約束條件下快速工作。使用EXPLAIN並添加適當的索引來支持你想要回答的查詢。如果你遇到過一個問題(並且我對你在這裏查詢的數據量有懷疑),決定解決瓶頸,然後當你真正知道可能是什麼問題而不是試圖解決問題時到目前爲止,只有想象。除了MySQL以外,還有其他技術可能會有所幫助 - 但您需要知道實際上是首先會損害您的性能。

0

處理像「indices_doctors_demos」這樣的非規格化表中行的爆炸的正常方法是規範化爲5NF。請記住,規範化與將ID號用作代理鍵的決定完全沒有關係。

在你描述的場景中,標準化爲5NF似乎很實用。你不會有任何超過700萬行的表。「indices_doctors_demos」表完全消失,四個「醫生」表全部變得更窄,並且它們都將以高度選擇性的索引結束。

如果你爲我工作,我會要求你證明5NF不能工作,然後我讓你採取不同的方法。

既然你已經有所有的數據,建立它並測試它,密切關注查詢計劃是有意義的。它不應該超過一個下午。猜測一些表名,我建議你將數據加載到這些表中。

-- You're missing foreign keys throughout. I've added some of them, 
-- but not all of them. I'm also assuming you have a way to identify 
-- doctors besides a bare integer. 
CREATE TABLE `doctors` (
    `doctor_id` int(10) NOT NULL AUTO_INCREMENT, 
    `city_id` int(10) NOT NULL DEFAULT '0', 
    `d_gender` char(1) NOT NULL DEFAULT 'U', 
    PRIMARY KEY (`doctor_id`) 
) ENGINE=InnoDB; 

CREATE TABLE `doctors_insurance` (
    `doctor_id` int(10) NOT NULL DEFAULT '0', 
    `insurance_id` int(10) NOT NULL DEFAULT '0', 
    PRIMARY KEY (`doctor_id`, `insurance_id`), 
    FOREIGN KEY (`doctor_id`) REFERENCES `doctors` (`doctor_id`), 
    FOREIGN KEY (`insurance_id`) REFERENCES `insurance` (`insurance_id`) 
) ENGINE=InnoDB; 

CREATE TABLE `doctors_languages` (
    `doctor_id` int(10) NOT NULL DEFAULT '0', 
    `language_id` int(10) NOT NULL DEFAULT '0', 
    PRIMARY KEY (`doctor_id`, `language_id`), 
    FOREIGN KEY (`doctor_id`) REFERENCES `doctors` (`doctor_id`), 
    FOREIGN KEY (`language_id`) REFERENCES `languages` (`language_id`) 
) ENGINE=InnoDB; 

CREATE TABLE `doctors_taxonomy` (
    `doctor_id` int(10) NOT NULL DEFAULT '0', 
    `taxonomy_id` int(10) NOT NULL DEFAULT '0', 
    PRIMARY KEY (`doctor_id`, `taxonomy_id`), 
    FOREIGN KEY (`doctor_id`) REFERENCES `doctors` (`doctor_id`), 
    FOREIGN KEY (`taxonomy_id`) REFERENCES `taxonomies` (`taxonomy_id`) 
) ENGINE=InnoDB;