代码之家  ›  专栏  ›  技术社区  ›  Jack M.

MySQL“发送数据”的速度非常慢

  •  15
  • Jack M.  · 技术社区  · 15 年前

    我有一张中等大小的桌子,目前有277k张唱片,我正试着做一个实验 FULLTEXT

    下表:

    CREATE TABLE `sqinquiries_inquiry` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `ts` datetime NOT NULL,
      `names` longtext NOT NULL,
      `emails` longtext NOT NULL,
      PRIMARY KEY (`id`),
      FULLTEXT KEY `sqinquiries_inquiry_search` (`names`,`emails`)
    ) ENGINE=MyISAM AUTO_INCREMENT=305560 DEFAULT CHARSET=latin1
    

    查询:

    SELECT * FROM `sqinquiries_inquiry` WHERE (
      MATCH (`sqinquiries_inquiry`.`names`) AGAINST ('smith' IN BOOLEAN MODE) OR
      MATCH (`sqinquiries_inquiry`.`emails`) AGAINST ('smith' IN BOOLEAN MODE)
    ) ORDER BY `sqinquiries_inquiry`.`id` DESC LIMIT 100
    

    (我删掉了看似无用的信息)

    +-------------------------+----------+
    | Status                  | Duration |
    +-------------------------+----------+
    | preparing               | 0.000014 | 
    | FULLTEXT initialization | 0.000015 | 
    | executing               | 0.000004 | 
    | Sorting result          | 0.000008 | 
    | Sending data            | 2.247934 | 
    | end                     | 0.000011 | 
    | query end               | 0.000003 | 
    +-------------------------+----------+
    

    DESCRIBE 看起来很棒,简单的一行: 描述如下:

    id: 1
    select_type: SIMPLE
    table: sqinquiries_inquiry
    type: index
    possible_keys: NULL
    key: PRIMARY
    key_len: 4 
    ref: NULL
    rows: 100
    Extra: Using where
    

    所以我不明白的是2.25秒发送数据的时间是从哪里来的?我在Python和控制台中看到了类似的性能 mysql 应用程序,两者都连接到 localhost .

    更新:

    • 根据请求平均行大小的注释,它是:53.8485
    • 根据评论,这里是 描述 在上面
    2 回复  |  直到 15 年前
        1
  •  33
  •   Quassnoi    15 年前

    这个 DESCRIBE

    但是,您的查询不使用 FULLTEXT 指数

    SELECT  *
    FROM    sqinquiries_inquiry
    WHERE   MATCH (names, emails) AGAINST ('smith' IN BOOLEAN MODE)
    ORDER BY
            id DESC
    LIMIT 100
    

    MATCH 仅当与定义索引的精确列集相匹配时才使用索引。

    因此,您的查询在上使用索引扫描 id Using index; Using where 在你生命的尽头

    Sending data 这是相当误导的:这实际上是上一个操作结束和当前操作结束之间经过的时间。

    例如,我刚刚运行了以下查询:

    SET profiling = 1;
    
    SELECT  *
    FROM    t_source
    WHERE   id + 1 = 999999;
    
    SHOW PROFILE FOR QUERY 39;
    

    其中返回了一行和此配置文件:

    'starting', 0.000106
    'Opening tables', 0.000017
    'System lock', 0.000005
    'Table lock', 0.000014
    'init', 0.000033
    'optimizing', 0.000009
    'statistics', 0.000013
    'preparing', 0.000010
    'executing', 0.000003
    'Sending data', 0.126565
    'end', 0.000007
    'query end', 0.000004
    'freeing items', 0.000053
    'logging slow query', 0.000002
    'cleaning up', 0.000005
    

    由于索引不可用, MySQL 需要执行全表扫描。

    0.126565 秒是从执行开始(读取第一行的时间)到执行结束(将最后一行发送到客户端的时间)的时间。

    最后一行位于表的末尾,查找并发送它花费了很长时间。

    P. S. 编辑以删除否决票:)

        2
  •  -9
  •   codymanix    15 年前

    不要选择*只选择您真正需要的列。

    如果表中包含要在结果中显示的大型文本字段,则可以使用子字符串仅传输文本的前几个字符/单词。

    一些客户端支持结果数据包的压缩。也许你想看看。