我有一个包含超过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)
我不够聪明,无法想出加快速度的方法,所以如果有人有任何建议,我将不胜感激,谢谢!
答案 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