2012-07-18 239 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