代码之家  ›  专栏  ›  技术社区  ›  Luke Bayes

简单的mysql查询需要2到3秒?

  •  3
  • Luke Bayes  · 技术社区  · 15 年前

    我运行了一个相当简单的过程,它定期提取RSS提要并更新MySQL数据库中的文章。

    文章表现在被填充到大约130K行。对于找到的每个项目,处理器检查该项目是否已经存在。这些查询几乎总是需要300毫秒,大约每10或20次尝试,它们需要2秒以上。

    SELECT id FROM `articles` WHERE (guid = 'http://example.com/feed.rss')  LIMIT 1;
    # Query_time: 2.754567  Lock_time: 0.000000  Rows_sent: 0  Rows_examined: 0
    

    我在guid列上有一个索引,但是每当遇到新的项目时,它就会被添加到项目表中——使查询缓存无效(对吗?).

    慢查询日志中的其他一些字段报告检查了120多行。

    当然,在我的开发机器上,这些查询大约需要0.2毫秒。

    服务器是EngineYardSolo(EC2)的虚拟主机,具有1.7GB的内存以及当今随附的任何CPU EC2。

    任何建议都将不胜感激。

    更新

    结果发现问题出在椅子和键盘之间。

    我在“id”上有索引,但在“guid”上查询。

    在“guid”上添加索引会使查询时间缩短到0.2毫秒。

    谢谢大家的帮助!

    4 回复  |  直到 15 年前
        1
  •  4
  •   derobert    15 年前

    运行:

    EXPLAIN SELECT id FROM `articles` WHERE (guid = 'http://example.com/feed.rss')  LIMIT 1;
    

    注意到 EXPLAIN 在前面。这会告诉你MySQL在做什么。很难相信从索引中探测一行可能需要2.7秒,除非您的机器严重超载和/或颠簸。考虑到行数为0,我猜想MySQL做了一次完整的表扫描,没有发现任何内容,这可能意味着您没有您认为需要的索引。

    回答你的另一个问题 任何 改为 articles 表,所有涉及该表的查询缓存项都将失效。

        2
  •  1
  •   Josh Davis    15 年前

    日志中说没有读取任何行,甚至没有检查任何行,因此问题不在您的查询上,而很可能在您的服务器上。EC2的致命弱点是它的IO/S,也许MySQL必须从磁盘加载索引,但是服务器的磁盘完全饱和了。

    如果您的索引足够小,可以放在内存中 (确保您的my.cnf为 key_buffer (MyISAM)或 innodb_buffer_pool_size (NYNDB) ,您应该能够使用

    SELECT guid FROM articles
    

    查看解释,确保它说“使用索引”。如果没有,这个应该:

    SELECT guid FROM articles FORCE INDEX (guid) WHERE LENGTH(guid) > 0
    

    或者,如果 guid 不是您的主键还是唯一的,您可以删除它的索引并创建另一个索引列,用于以索引大小的一小部分快速检索记录。专栏 guid_crc32 将是一个无符号的int,并将保存 GUID

    ALTER TABLE articles ADD COLUMN guid_crc32 INT UNSIGNED, ADD INDEX guid_crc32 (guid_crc32);
    UPDATE articles SET guid_crc32 = CRC32(guid);
    

    然后,您的选择查询将如下所示:

    SELECT id FROM articles WHERE guid = 'http://example.com/feed.rss' AND guid_crc32 = CRC32('http://example.com/feed.rss') LIMIT 1;
    

    优化器应该使用上的索引 GudioCRC32 ,这应该比搜索速度更快、更小 GUID .

        3
  •  0
  •   Nir Levy    15 年前

    如果这个表经常更新,那么MySQL可能无法正确更新索引计数。尝试“检查表文章”以更新索引计数,并查看表是否良好。

    另外,尝试看看在查询上进行解释是否在开发和生产机器上得到相同的结果。如果结果不同,请尝试优化表。

    这些是myisam表还是innodb表?

        4
  •  0
  •   Jeff Ferland    15 年前

    假设guid是被索引的,id是您的主键,那么就出现了“错误”。在这种情况下,它是一个只包含索引的查询。索引正在从内存中缓冲,磁盘可能正忙着。

    根据您的更新/插入/删除模式,数据库可能需要一个“优化”命令。

    我想查看的SQL命令输出:

    show table status like 'articles';
    explain SELECT id FROM `articles` WHERE (guid = 'http://example.com/feed.rss')  LIMIT 1;
    explain articles;
    

    我想查看的系统命令输出(假设是Linux):

    iostat 5 5
    

    告诉我们,因为1.7MB是错误的,或者发生了一些非常令人兴奋的事情,您有多少内存。

    编辑 您的SQL Server在my.cnf中有多少可用内存?