3

我有一个数据库,其中包含超过 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)

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

4

1 回答 1

3

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

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

这也避免了准备大量行以返回给客户端并在不需要时将它们返回给客户端的开销。

def此外,如果您的查询正在大表中查找“大海捞针”,则作为前导列的索引(至少在您最大的表上)可能会提高性能。


更新:

我重新阅读了您的问题,我看到您有 30,000 个表要检查,即 30,000 个单独的查询,30,000 次到数据库的往返。(ACCCKKK。)

所以我之前的建议几乎没有用。(这将更适合 40 个表,每个表有 30,000 行。)

另一种方法是同时查询一堆这些表。不过,我什至会犹豫一次尝试超过几百张桌子,所以我会分批进行。

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. 如果您遇到的表中没有该列,则整个批次都会失败。并且 aSHOW 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
于 2012-07-18T19:56:02.513 回答