MySQL Python花了太长时间来查询大型数据库

时间:2012-07-18 19:14:51

标签: python mysql performance

我有一个包含超过30,000个表的数据库,每个表中有大约40-100行。我想检索一个包含特定列下的字符串的表名列表。

例如:

我想检索包含'foo'...

的所有表的名称
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)

我不够聪明,无法想出加快速度的方法,所以如果有人有任何建议,我将不胜感激,谢谢!

1 个答案:

答案 0 :(得分:3)

如果您只是测试每个表def = 'str'中是否存在一行,那么一件简单的事情(没有其他更改)就是在您的结尾添加LIMIT 1子句查询。

(如果您的查询正在执行全表扫描,MySQL可以在找到第一行后暂停它。如果没有找到行,则全表扫描必须运行到表的末尾。)

这也避免了准备将大量行返回给客户端并将其返回给客户端的开销,如果不需要的话。

此外,如果您的查询通过大表查找“大海捞针”,那么def作为前导列(至少在最大的表中)的索引可能会有助于提高性能。


更新:

我重新阅读了你的问题,我发现你有30,000个表需要检查,这是30,000个单独的查询,30,000次往返数据库。 (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