2012-07-18 238 views
3

我有一個數據庫,每個表中有超過30,000個表和〜40-100行。我想檢索包含特定列下的字符串的表名稱列表。MySQL Python花費太長時間來查詢大型數據庫

因此,例如:

我想要檢索包含「富」的所有表的名字...

Database 
    Table_1 
     ID: 1, STR: bar 
     ID: 2, STR: foo 
     ID: 3, STR: bar 
    Table_2 
     ID: 1, STR: bar 
     ID: 2, STR: bar 
     ID: 3, STR: bar 
    Table_3 
     ID: 1, STR: bar 
     ID: 2, STR: bar 
     ID: 3, STR: foo 
在這種情況下,函數返回[「TABLE_1」

所以,' Table_3']

到目前爲止,我有這個,它工作正常,但需要2分鐘的時間來執行,這對於我想要的應用程序來說太長了。

self.m('SHOW TABLES') 
result = self.db.store_result() 
tablelist = result.fetch_row(0, 1) 
for table in tablelist: 
    table_name = table['Tables_in_definitions'] 
    self.m("""SELECT `def` FROM `""" + table_name + """` WHERE `def` = '""" + str + """'""") 
    result = self.db.store_result() 
    r = result.fetch_row(1, 1) 
    if len(r) > 0: 
     results.append(table_name) 

我不夠聰明想出一種方法來加快這一點,所以如果任何人有任何建議,將不勝感激,謝謝!

回答

3

如果您只是測試每個表中是否存在一行,其中def = 'str',一個容易做的事(無其他更改)是在查詢的末尾添加LIMIT 1子句。

(如果你的查詢執行全表掃描,MySQL能阻止它曾經的第一行中找到。如果沒有找到行,全表掃描已運行到表的末尾。)

這也避免了準備大量要返回給客戶端的行並將其返回給客戶端(如果不需要)的開銷。

另外,如果您的查詢是通過大型表格查找「乾草堆裏的針」,那麼以def作爲主要列(至少在您的最大表格上)的索引可能有助於提高性能。


UPDATE:

我已經重讀你的問題,我看到你有30000個表來檢查,這是30,000個不同的查詢30000個往返到數據庫。 (ACCCKKK)

所以我以前的建議幾乎沒用。 (對於每個具有30,000行的40個表,這將是更合適的)。

另一種方法是同時查詢一堆表。儘管我每次都嘗試超過幾百張桌子,但我會猶豫不決,所以我會分批進行。

SELECT DISTINCT 'Table1' AS table_name FROM Table1 WHERE def = 'str' 
UNION ALL 
SELECT DISTINCT 'Table2' FROM Table2 WHERE def = 'str' 
UNION ALL 
SELECT DISTINCT 'Table3' FROM Table3 WHERE def = 'str' 

如果def在每個表中是唯一,或者,如果它幾乎是唯一的,你可以處理返回重複table_name的值,你可以擺脫DISTINCT關鍵字。

您確實需要確保列表中的每個表都有一個名爲def的列。如果遇到沒有該列的表,則整個批次將失敗。並且SHOW TABLES不會對列名稱進行檢查。我會用這樣的查詢來獲取有一列名爲def表名的列表:

SELECT table_name 
    FROM information_schema.columns 
WHERE table_schema = DATABASE() 
    AND column_name = 'def' 
GROUP BY table_name 
ORDER BY table_name 
+0

感謝您的評論,「高清」是唯一的,這樣像你說的,我只是檢查每個表中有1行。我會看看LIMIT 1中的表現是否有所提高,並使其成爲領先專欄。 – amba88 2012-07-18 20:02:33

+0

我已經更新了我的答案......我更仔細地閱讀了您的問題,並且我不認爲我的第一個建議(使用LIMIT 1)會幫助很多......您沒有花時間掃描表格,您可能會花費大部分時間爲數據庫創建30000次以上的往返運行,以運行快速運行的查詢。更好的方法是使用UNION ALL方法同時查詢多個表,並讓查詢返回table_name中的行。 – spencer7593 2012-07-18 20:29:04

+0

好吧,非常感謝您的建議,我會嘗試使用UNION所有的方法,看看會發生什麼。表名都是唯一的,每個表都有一個def列,所以我認爲SHOW TABLES應該足夠了。 – amba88 2012-07-18 21:05:08