2012-07-02 95 views
4

我在典型的共享主机服务产品上运行一组自我开发的应用程序。我根据基于D/B元数据前缀的表列表将静态配置的允许表中的表列表移动到一个表中。当我确实将此版本推广到公共服务时,我的每个请求延迟平均增加了2.3-2.4秒。有些仪器显示,这完全归结为一个SQL查询:对information_schema.tables的缓慢查询

SELECT TABLE_NAME AS name 
FROM information_schema.tables 
WHERE TABLE_SCHEMA = '<DBname>' 
AND TABLE_NAME LIKE '<TablePrefix>%'; 

我用这个是因为我想明确地命名结果集中的列。但是,解决这个编码与替代查询增加了一个额外的代码行跑在< 2毫秒

SHOW TABLES LIKE '<TablePrefix>%'; 

我的服务提供商使用MySQL的企业这样5.0.92-50我不能做任何分析。这是一个扩展问题,因为它不会发生在我可以配置的我的开发环境和测试虚拟机上。它们支持数以千计的用户,所以活动模式将会非常大,但即使如此连接和大多数查询也只需要几毫秒。

有谁知道为什么在大型多用户系统上查询基于内存的information_schema需要很长时间?

回答

1

信息模式未优化,没有索引,只有带有元数据的表,通常,当您从模式运行SELECT时,它会打开并读取文件。

看看这篇文章 - Optimizing INFORMATION_SCHEMA Queries;在某些情况下它会帮助你。

+1

Devant,谢谢你。我在表名中为我的'prefix_%'like子句使用了一个常量DB名称和常量模式,因此查询接近最佳。不过,我也检查过本节的5.0和5.1版本。 5.1版本澄清说这些性能优化只是5.1.21引入的,因此我认为不适用于5.0.92。所以最好MySQL引擎正在做一个数据库目录扫描来返回这些信息。本表中的“ENGINE = MEMORY”条款具有误导性。我仍然无法确定的是剧集版本如此之快的原因。 – TerryE

+1

我为** SHOW TABLES LIKE **语句做了mysqld的strace,并且这样做了DB dir的** openat()**,获取dir条目,然后打开匹配模式的表的每个FRM文件,但这些都在我系统的VFAT缓存中,所以这需要几毫秒。 SELECT语句事件更快,因为它执行相同的操作** openat()+ getents()**但不打开FRM文件。所以我想这是我的托管服务提供商仍然使用MySQL 5.0的一项功能。 – TerryE

+0

您的ans让我的方向正确,帮助我自己回答问题。遗憾的是,我抛弃了我的旧版Ubuntu 8.04虚拟机,因此我没有运行MySQL 5.0的LAMP堆栈,但我很高兴I_S查询的未优化方面和完整的扫描是根本问题。 – TerryE

8

对于那些谁可能想用一个小缺点黑客攻击:http://www.mysqlperformanceblog.com/2011/12/23/solving-information_schema-slowness/

它所做的是它禁用一些统计数据,如果您查询的模式得到更新,更多的信息在这里:http://dev.mysql.com/doc/refman/5.1/en/innodb-parameters.html#sysvar_innodb_stats_on_metadata

又使事情变得更容易懒惰烧伤不想读谁,你只需要进行更改设置:

innodb_stats_on_metadata=0 

您可以在配置文件或动态做到这一点:

mysql> set global innodb_stats_on_metadata=0; 
+0

感谢这个反馈,但这是MyISAM问题上的一个MySQL,并且我最终将5.0和5.1的MYSQL守护进程置于底层。你的修复不会帮助OQ。 – TerryE

+0

请注意innodb_stats_on_metadata设置在MySQL 5.0中不可用 –