代码之家  ›  专栏  ›  技术社区  ›  Echo says Reinstate Monica

帮助优化MySQL查询

  •  0
  • Echo says Reinstate Monica  · 技术社区  · 16 年前

    我不能让我的这个查询在一个大表(200k+行)上使用索引,它正在对它进行全表扫描。现在查询大约需要1.2秒。如果可能的话,我想把时间缩短到0.2秒以内。

    我的问题是:

    SELECT st_issues.issue_id, st_issues.cat_id,st_categories.name AS cat_name, st_issues.status_id,st_statuses.name AS status_name, st_issues.priority_id,st_priorities.name AS priority_name,st_priorities.color AS color, st_issues.assigned_cid,assigned_u.firstname,assigned_u.lastname,assigned_u.screenname, message, rating, created_by_email,created_by_cid,created_by_uid,by_user.firstname AS by_firstname,by_user.lastname AS by_lastname,by_user.screenname AS by_screenname, st_issues.browser,from_url,created_by_store,created,st_issues.stamp
    FROM st_issues
     JOIN st_categories ON (st_issues.cat_id=st_categories.cat_id)
     JOIN st_statuses ON (st_issues.status_id=st_statuses.status_id)
     JOIN st_priorities ON (st_issues.priority_id=st_priorities.priority_id)
     LEFT JOIN users AS assigned_u ON (assigned_u.cid=st_issues.assigned_cid)
     LEFT JOIN users AS by_user ON (by_user.uid=st_issues.created_by_uid)
     LEFT JOIN st_issue_changes ON (st_issues.issue_id=st_issue_changes.issue_id AND change_id=0)
    WHERE st_issues.assigned_cid=0
    

    结果表明:

    1, 'SIMPLE', 'st_issues', 'ALL', '', '', , '', 4, 'Using where'
    1, 'SIMPLE', 'st_categories', 'eq_ref', 'PRIMARY', 'PRIMARY', 1, 'sg.st_issues.cat_id', 1, ''
    1, 'SIMPLE', 'st_priorities', 'eq_ref', 'PRIMARY', 'PRIMARY', 1, 'sg.st_issues.priority_id', 1, ''
    1, 'SIMPLE', 'assigned_u', 'ref', 'cid', 'cid', 8, 'sg.st_issues.assigned_cid', 1, ''
    1, 'SIMPLE', 'st_statuses', 'ALL', 'PRIMARY', '', , '', 4, 'Using where'
    1, 'SIMPLE', 'by_user', 'ALL', '', '', , '', 221623, ''
    1, 'SIMPLE', 'st_issue_changes', 'eq_ref', 'PRIMARY', 'PRIMARY', 6, 'sg.st_issues.issue_id,const', 1, ''
    

    显然,问题在于“by_user”上的连接,因为它没有使用索引。

    CREATE TABLE  `users` (
      `cid` double unsigned NOT NULL auto_increment,
      `uid` varchar(20) NOT NULL default '',
    ...
      `firstname` varchar(20) default NULL,
      `lastname` varchar(20) default NULL,
    ...
      PRIMARY KEY  (`uid`),
    ...
    ) ENGINE=InnoDB
    


    有人对如何加快查询速度有什么想法或提示吗?

    编辑:

    CREATE TABLE  `st_issues` (
      `issue_id` int(10) unsigned NOT NULL auto_increment,
      `cat_id` tinyint(3) unsigned NOT NULL default '0',
      `status_id` tinyint(3) unsigned NOT NULL default '0',
      `priority_id` tinyint(3) unsigned NOT NULL default '0',
      `assigned_cid` int(10) unsigned NOT NULL default '0',
      `rating` tinyint(4) default NULL,
      `created_by_email` varchar(255) NOT NULL default '',
      `created_by_cid` int(10) unsigned NOT NULL default '0',
      `created_by_uid` varchar(20) NOT NULL default '',
      `created_by_store` tinyint(3) unsigned NOT NULL default '0',
      `browser` varchar(255) NOT NULL default '',
      `from_url` varchar(255) NOT NULL default '',
      `created` datetime NOT NULL default '0000-00-00 00:00:00',
      `stamp` datetime NOT NULL default '0000-00-00 00:00:00',
      PRIMARY KEY  (`issue_id`),
      KEY `idx_create_by_cid` (`created_by_cid`),
      KEY `idx_create_by_uid` (`created_by_uid`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    2 回复  |  直到 16 年前
        1
  •  3
  •   bobince    16 年前

    )引擎=InnoDB

    而《圣约》杂志称:

    如果您的两个表使用不同的排序规则,那么uid和由uid创建的两种字符串数据类型是不同的,MySQL必须在比较它们之前执行字符集强制,从而破坏索引。

        2
  •  0
  •   Bill Karwin    16 年前

    • 添加索引 st_issues.assigned_cid

    • 更改的主键 users 表到 cid 而不是 uid .

    • 更改的联接条件 by_user cid 而不是 :

      LEFT JOIN users AS by_user ON (by_user.cid=st_issues.created_by_cid)
      

    EXPLAIN 报告(尽管没有数据行):

    +----+-------------+------------------+--------+---------------+--------------+---------+-------------------------------+------+-------------+
    | id | select_type | table            | type   | possible_keys | key          | key_len | ref                           | rows | Extra       |
    +----+-------------+------------------+--------+---------------+--------------+---------+-------------------------------+------+-------------+
    |  1 | SIMPLE      | st_issues        | ref    | assigned_cid  | assigned_cid | 4       | const                         |    1 |             | 
    |  1 | SIMPLE      | st_categories    | eq_ref | PRIMARY       | PRIMARY      | 1       | test.st_issues.cat_id         |    1 |             | 
    |  1 | SIMPLE      | st_statuses      | eq_ref | PRIMARY       | PRIMARY      | 1       | test.st_issues.status_id      |    1 |             | 
    |  1 | SIMPLE      | st_priorities    | eq_ref | PRIMARY       | PRIMARY      | 1       | test.st_issues.priority_id    |    1 |             | 
    |  1 | SIMPLE      | assigned_u       | eq_ref | PRIMARY       | PRIMARY      | 8       | test.st_issues.assigned_cid   |    1 |             | 
    |  1 | SIMPLE      | by_user          | eq_ref | PRIMARY       | PRIMARY      | 8       | test.st_issues.created_by_cid |    1 |             | 
    |  1 | SIMPLE      | st_issue_changes | eq_ref | PRIMARY       | PRIMARY      | 8       | test.st_issues.issue_id,const |    1 | Using index | 
    +----+-------------+------------------+--------+---------------+--------------+---------+-------------------------------+------+-------------+
    

    我建议的另一件事是定义查找表 st_categories st_statuses 用一个 自然键 st_issues 表,而不是使用 tinyint 圣卢西亚问题 桌子