2011-06-02 30 views
3

我目前正在嘗試構建一個嚴重依賴郵政編碼數據(從OS CodePoint Open提供)的Web應用程序。郵政編碼數據庫有120個表格,這些表格分解了最初的郵政編碼前綴(即SE,WS,B)。在這些桌子裏面有11k - 48k行與3個領域(郵編,緯度,Lng)。PHP/MySQL - 查詢性能注意事項(僅供選擇)48k行

我需要做的是讓用戶上網,輸入他們的郵編,即SE1 1LD,然後選擇SE表,並將郵政編碼轉換爲經緯度。

我很滿意這樣做在PHP級別。我擔心的是......以及將要查詢的大量行,以及是否要讓我的網站停止運行?

如果有什麼技術我應該知道,請讓我知道..我從來沒有與大數字表工作!

謝謝:)

+0

所以,你的意思是說有一個'SE'表,一個'WS',一個'B'等,所有結構都相同(Postcode,Lat,Lng)'?他們沒有聽說過正常化嗎? – 2011-06-02 11:16:41

+0

我假設他們這樣做是爲了保持文件的大小。查詢170萬行會導致問題? – lethalMango 2011-06-02 11:27:33

+0

通過適當的索引,查詢具有數百萬行的表格可以非常快速。如果一個查詢返回幾行,並且有索引可以使用,那麼它不必搜索整個表,它使用索引(es)。然後從磁盤中檢索幾行。 – 2011-06-02 11:35:57

回答

1

如果我理解正確的,有一個SE表,WS一個,一個B一個等。在所有,表120具有相同的結構(Postcode, Lat, Lng)

我強烈建議你正常化的表格。

您可以具有一個表:

postcode(prefix, postcode, lat, lng) 

或兩個:

postcode(prefixid , postcode, lat, lng) 

prefix(prefixid, prefix) 

的郵政編碼表將性能稍微大於11K-48K行,大約30K×120 = 3.6M行,但更大的它會節省您爲每個前綴編寫不同查詢的時間,例如,如果您想要搜索經度和緯度(想象一個在120個表中搜索的查詢),則可以爲每個前綴編寫不同的查詢。

如果您不確定嘗試添加person表,那麼您可以爲用戶添加數據。這張表如何與郵政編碼表相關?


編輯

由於prefix只是postcode這也是primary key的第一個字符,則不需要額外的字段或第二個表。我會簡單地將120個表合併爲一個:

postcode(postcode, lat, lng) 

然後查詢:

SELECT * 
FROM postode 
WHERE postcode = 'SE11LD' 

SELECT * 
FROM postode 
WHERE postcode LIKE 'SE%' 

將會很快,因爲他們將要使用的主鍵索引。

+0

前綴不是問題,只用於查找正確的查詢表,即'NE1 2GB'將使用'NE'選擇'NE'表,然後查詢'NE12GB'以選擇其'lat '和'lng'值。查詢3mil行會導致放緩與查詢單獨的表? – lethalMango 2011-06-02 11:34:36

+0

如果在字段'(郵政編碼)'上有一個索引,則差異將是最小的。使用一個(標準化)表格的好處,從長遠來看是巨大的。 – 2011-06-02 11:39:25

4

48K不是大數。是4800萬。 :)如果您的表格已正確編制索引(將索引放在WHERE條款中使用的字段中),則根本不會有問題。

避免LIKE,如果可能,請使用INNER JOINS而不是LEFT JOIN。

+2

嗯,我從來不知道!哈哈,謝謝你。郵政編碼將是PK的,所以我會假設,除了查詢不應該導致太多的問題? – lethalMango 2011-06-02 11:02:43

+0

在pma或終端運行幾個查詢,看看時間是什麼,不應該超過幾個毫秒 – dogmatic69 2011-06-02 11:03:49

+0

太棒了,謝謝你們! – lethalMango 2011-06-02 11:06:06

4

從mysql中選擇48k行並不大,實際上它很小。索引它正確,你很好。

0

只要您在適當的列上有索引,就不會有問題。我的一個客戶有存儲在像表中的郵政編碼數據庫:

CREATE TABLE `postcode_geodata` (
`postcode` varchar(8) NOT NULL DEFAULT '', 
`x_coord` float NOT NULL DEFAULT '0', 
`y_coord` float NOT NULL DEFAULT '0', 
UNIQUE KEY `postcode_idx` (`postcode`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 | 

,我們在查詢是沒有問題(從性能的角度來看)。

如果你的表確實變得非常大,那麼你總是可以看看使用MySQL的分區支持 - 見http://dev.mysql.com/doc/refman/5.1/en/partitioning.html - 但我不會看,直到你完成了更容易的事情(見下文)。

如果您認爲性能問題,請打開MySQL的slow_query_log(請參閱/etc/mysql/my.cnf)並查看它的含義(您也可以在此處找到命令'mysqldumpslow',用於分析緩慢查詢日誌)。

也嘗試在MySQL cli上使用'explain'語法 - 例如

EXPLAIN SELECT a,b,c FROM table WHERE d = 'foo' and e = 'bar' 

這些步驟將幫助您優化數據庫 - 通過識別哪些索引(或不)用於查詢。

最後,還有mysqltuner.pl腳本(請參閱http://mysqltuner.pl),它可以幫助您優化MySQL服務器的設置(例如查詢緩存,內存使用情況等,這會影響I/O並因此影響性能/速度)。