当前位置: 首页 > 知识库问答 >
问题:

MySQL连接优化-绕过文件ort

高寒
2023-03-14

优化MySQL左联接仍然有问题。该查询需要0.13秒才能完成,而下一个查询需要0.00秒(简化)。

对于该查询,我希望达到0.00左右。

SELECT 
  SQL_NO_CACHE p.id 
FROM 1_posts p 
  INNER JOIN 1_topics t 
    ON (p.cid = t.cid && p.container = t.id) 
WHERE 
  t.cid = 1010699 
ORDER BY 
  p.id DESC 
LIMIT 1;

解释输出:

+----+-------------+-------+------+-------------------+-------+---------+---------------------+------+----------------------------------------------+
| id | select_type | table | type | possible_keys     | key   | key_len | ref                 | rows | Extra                                        |
+----+-------------+-------+------+-------------------+-------+---------+---------------------+------+----------------------------------------------+
|  1 | SIMPLE      | t     | ref  | PRIMARY,cid,cid_2 | cid   | 4       | const               |  216 | Using index; Using temporary; Using filesort |
|  1 | SIMPLE      | p     | ref  | PRIMARY,cid,cid_2 | cid_2 | 8       | const,forumdb.t.id |   12 |                                              |
+----+-------------+-------+------+-------------------+-------+---------+---------------------+------+----------------------------------------------+

现在,同样的简化查询运行良好(使用索引等,唯一的区别在于括号之间):

SELECT 
  SQL_NO_CACHE p.id 
FROM 
  1_posts p 
  INNER JOIN 1_topics t 
    ON (p.cid = t.cid) 
WHERE 
  t.cid = 1010699 
ORDER BY 
  p.id DESC 
LIMIT 1;

解释说:

+----+-------------+-------+-------+-------------------+---------+---------+-------+-------+--------------------------+
| id | select_type | table | type  | possible_keys     | key     | key_len | ref   | rows  | Extra                    |
+----+-------------+-------+-------+-------------------+---------+---------+-------+-------+--------------------------+
|  1 | SIMPLE      | p     | range | PRIMARY,cid,cid_2 | PRIMARY | 4       | NULL  | 31720 | Using where; Using index |
|  1 | SIMPLE      | t     | ref   | PRIMARY,cid,cid_2 | cid_2   | 4       | const |   194 | Using index              |
+----+-------------+-------+-------+-------------------+---------+---------+-------+-------+--------------------------+
CREATE TABLE `1_posts` (
  `cid` int(20) unsigned NOT NULL DEFAULT '0',
  `id` int(20) unsigned NOT NULL AUTO_INCREMENT,
  `container` int(20) unsigned NOT NULL DEFAULT '0',
  `creator` int(20) unsigned NOT NULL DEFAULT '0',
  `ref` int(20) unsigned DEFAULT NULL,
  `timestamp` int(20) unsigned NOT NULL DEFAULT '0',
  `posticon` tinyint(11) DEFAULT NULL,
  `last_edited_ts` int(10) unsigned DEFAULT NULL,
  `last_edited_by` int(20) unsigned DEFAULT NULL,
  `signature` varchar(250) DEFAULT NULL,
  `client_ip` int(10) unsigned NOT NULL DEFAULT '0',
  `data_format` tinyint(20) unsigned DEFAULT NULL,
  `use_bbcode` tinyint(3) unsigned NOT NULL DEFAULT '1',
  `use_smileys` tinyint(3) unsigned NOT NULL DEFAULT '1',
  `topic_hash` int(10) unsigned NOT NULL DEFAULT '0',
  `del_ts` int(10) unsigned NOT NULL DEFAULT '0',
  `del_reason` tinyint(4) NOT NULL DEFAULT '0',
  PRIMARY KEY (`cid`,`id`),
  UNIQUE KEY `cid` (`cid`,`topic_hash`,`container`,`id`,`del_ts`),
  KEY `cid_2` (`cid`,`container`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8


CREATE TABLE `1_topics` (
  `cid` int(10) unsigned NOT NULL DEFAULT '0',
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `container` int(20) NOT NULL DEFAULT '0',
  `name` varchar(128) NOT NULL DEFAULT '',
  `creator` int(20) unsigned NOT NULL DEFAULT '0',
  `last_modified` int(20) unsigned NOT NULL DEFAULT '0',
  `views` int(11) NOT NULL DEFAULT '0',
  `closed` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `sticky` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `last_post_id` int(20) unsigned DEFAULT NULL,
  `num_posts` int(10) unsigned DEFAULT NULL,
  `lp_ts` int(20) unsigned NOT NULL DEFAULT '0',
  `posticon` smallint(5) unsigned DEFAULT NULL,
  `hidden` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `topic_change_ts` int(10) unsigned NOT NULL DEFAULT '0',
  `topic_hash` int(10) unsigned NOT NULL DEFAULT '0',
  `forum_hash` int(10) unsigned NOT NULL DEFAULT '0',
  PRIMARY KEY (`cid`,`id`),
  KEY `container` (`container`),
  KEY `last_modified` (`last_modified`),
  KEY `sticky` (`sticky`),
  KEY `topic_hash` (`topic_hash`),
  KEY `forum_hash` (`forum_hash`),
  KEY `cid` (`cid`,`id`),
  KEY `cid_2` (`cid`),
  FULLTEXT KEY `name` (`name`)
) ENGINE=MyISAM AUTO_INCREMENT=211963 DEFAULT CHARSET=latin1
+----+-------------+-------+------+-------------------------------+-------+---------+---------------------+------+----------------------------------------------+
| id | select_type | table | type | possible_keys                 | key   | key_len | ref                 | rows | Extra                                        |
+----+-------------+-------+------+-------------------------------+-------+---------+---------------------+------+----------------------------------------------+
|  1 | SIMPLE      | t     | ref  | PRIMARY,cid,cid_2             | cid   | 4       | const               |  212 | Using index; Using temporary; Using filesort |
|  1 | SIMPLE      | p     | ref  | PRIMARY,cid,cid_2,cid_3,cid_4 | cid_3 | 8       | const,forumdb.t.id |   11 | Using index                                  |
+----+-------------+-------+------+-------------------------------+-------+---------+---------------------+------+----------------------------------------------+

共有1个答案

苏宏逸
2023-03-14

此版本使用正确的索引:

SELECT SQL_NO_CACHE p.id
FROM 1_posts p INNER JOIN
     1_topics t
     ON (p.cid = t.cid)
WHERE t.cid = 1010699
ORDER BY p.id DESC LIMIT 1;

此版本不:

SELECT SQL_NO_CACHE p.id
FROM 1_posts p INNER JOIN
     1_topics t
     ON (p.cid = t.cid && p.container = t.id);
WHERE t.cid = 1010699
ORDER BY p.id DESC
LIMIT 1;

在第一个中,MySQL可以首先对WHERE子句(cid列在索引中的第一个)使用L_posts(cid,id)上的索引,然后对联接(同一列)使用索引。然后它可以使用相同的索引进行排序--id是索引中的下一列。(顺便说一下,这使用了MySQL优化器的一个特性,该特性将WHERE子句中的=条件从T传播到P。)

要让第二个版本使用索引,请在l_posts(cid,container,id)上定义一个索引。

 类似资料:
  • 该查询占用了tmp目录中的3GB+并最终超时。我这里少了点什么,怎样才能提高效率?我在这里的目标只是添加到现有查询中,以便从额外的表(j25_mt_cfvalues)中获取值。 : j25_mt_cats模式:

  • 下面说的优化基于 MySQL 5.6,理论上 5.5 之后的都算适用,具体还是要看官网 服务状态查询 查看当前数据库的状态,常用的有: 查看系统状态:SHOW STATUS; 查看刚刚执行 SQL 是否有警告信息:SHOW WARNINGS; 查看刚刚执行 SQL 是否有错误信息:SHOW ERRORS; 查看已经连接的所有线程状况:SHOW PROCESSLIST; 查看当前连接数量:SHOW

  • 在整体的系统运行过程中,数据库服务器 MySQL 的压力是最大的,不仅占用很多的内存和 cpu 资源,而且占用着大部分的磁盘 io 资源,连 PHP 的官方都在声称,说 PHP 脚本 80% 的时间都在等待 MySQL 查询返回的结果。由此可见,提高系统的负载能力,降低 MySQL 的资源消耗迫在眉睫。 常见优化方法: 1、页面缓存 1、页面缓存功能是降低MySQL的资源消耗的(PHPCMS V9

  • 问题内容: 我想在我的网页中进行全文搜索。我需要分页进行搜索。我的数据库每张表有50,000+行。我已经改变了我的表,并使其成为索引。该表始终处于更新状态,仍然有一个自动增加的列。而最新的总是在表格的末尾。 但整个查询时间将花费。我通过Google搜索了许多文章,有的文章写道,只有限制字段字长才能帮助更快地进行搜索。但作为一种类型,它会像这样改变一定的长度(我尝试过标题TEXT(500) CHAR

  • 问题内容: 我已编写此代码来加入ArrayList元素:是否可以对其进行更多优化?还是有其他更好的方法? 问题答案: 这就是著名的java.util.Collection团队的工作方式,所以我认为这应该很好;) 另外,这就是用达菲(Duffymo)的答案得到逗号分隔符的方法;)

  • 有谁能帮我找到这个命令吗?命令是 如果我错了,请纠正我,但正如我所看到的,这将压缩当前目录中的文件,同时它将其复制到目标位置,对吗?这是否意味着当前文件将是完整的(不会被压缩)?