【问题标题】:Optimize query to information_schema优化对information_schema的查询
【发布时间】:2011-10-10 21:00:42
【问题描述】:

我运行的网站执行了大量搜索。这些搜索很重要,并且有多个数据需要加入到结果中。

我的解决方案是将搜索结果存储在两个表中:搜索和搜索结果

Searches 包含搜索的元数据

Searchresults 包含两列 idsearch、iddata 和一个内存表

为了防止搜索结果的内存溢出,我们会定期修剪这张表并刷新过时的数据。据我了解,内存表具有表级锁定,因此在修剪期间,searchresults 表被阻塞并导致站点性能下降。

解决方案是为每个搜索创建一个新表,然后在搜索过时时删除此 searchresults_xxxx 表。

我首先删除搜索表中的旧条目。然后执行以下操作:

select table_name
from information_schema.tables
where 
    table_schema = 'mysite_datawarehouse' 
    and table_name not in (select concat('searchresults_', idsearch) from searches);

通常有数千个匹配项,导致平均查询时间约为 30 秒左右。在此期间,性能再次下降,我又回到了原点。有没有更好的方法来写这个?或者也许是一种更好的方式来构建它?

谢谢!

【问题讨论】:

  • 你能定期定义吗?如果您的意思是每晚凌晨 2 点,那么需要 30 秒是否重要?如果你白天做,你只能在晚上做吗?为了改进您的查询,您可以将其转换为联接。 not in 如果您的表对它们有任何大小,可能会很讨厌。
  • 每 10 分钟搜索一次无效。搜索在被清理之前通常有大约 5k 行。每个搜索通常在 searchresults 中存储约 1k 到 20k 的结果。所以清除旧的结果变得相当重要。

标签: mysql


【解决方案1】:

我刚刚询问并解决了一个相关问题:Slow query on information_schema.tables。您在这里遇到的问题是查询将通过对 *.FRM 文件进行目录扫描来枚举数据目录中的所有表。它还可以打开每个 FRM 文件并读取其标题。这会很慢。

我的问题是为什么要查询信息架构?我假设您信任搜索的内容。为什么不在 searches 中包含一个创建时间戳字段并选择创建 rimestamp 早于某个年龄的所有表名。如果它那么直接做一个循环,如果存在一个删除表,甚至将这个清理过程移动到一个存储过程中。对信息模式进行主要查询不会增加任何内容,并且会减慢修剪过程。

【讨论】:

    【解决方案2】:

    这是您的原始查询

    select table_name
    from information_schema.tables
    where 
        table_schema = 'mysite_datawarehouse' 
        and table_name not in
        (select concat('searchresults_', idsearch) from searches);
    

    如果有一堆 InnoDB 表需要浏览,我很容易认为它会很慢

    尝试重构查询查询以执行 LEFT JOIN,如下所示:

    select A.table_name
    from (select concat('searchresults_', idsearch) table_name from searches) A
    LEFT JOIN
    (select table_name FROM information_schema.tables
    where table_schema = 'mysite_datawarehouse') B
    USING (table_name)
    WHERE B.table_name IS NULL;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-12
      • 2011-08-03
      相关资源
      最近更新 更多