我的Appliation(使用php)性能非常慢,因为我的mysql表中有更多数据,我的表格结构如下,
`CREATE TABLE `xxxxx`
(`ID` int(11) NOT NULL AUTO_INCREMENT,
`IP` varchar(45) NOT NULL,
`Cname` varchar(45) NOT NULL,
`Port` int(5) NOT NULL DEFAULT'3306',
`Variable` varchar(150) DEFAULT NULL,
`status` varchar(100) DEFAULT NULL,
`moddate` datetime NOT NULL,
`Servertime` datetime NOT NULL,
PRIMARY KEY (`ID`,`moddate`),
KEY `idx_variable` (`Variable`) )
ENGINE=InnoDB AUTO_INCREMENT=85054928 DEFAULT CHARSET=ucs2
/*!50100 PARTITION BY LIST ( MONTH (moddate))
(PARTITION Jan VALUES IN (1) ENGINE = InnoDB,
PARTITION Feb VALUES IN (2) ENGINE = InnoDB,
PARTITION Mar VALUES IN (3) ENGINE = InnoDB,
PARTITION Apr VALUES IN (4) ENGINE = InnoDB,
PARTITION May VALUES IN (5) ENGINE = InnoDB,
PARTITION Jun VALUES IN (6) ENGINE = InnoDB,
PARTITION Jul VALUES IN (7) ENGINE = InnoDB,
PARTITION Aug VALUES IN (8) ENGINE = InnoDB,
PARTITION Sep VALUES IN (9) ENGINE = InnoDB,
PARTITION Oct VALUES IN (10) ENGINE = InnoDB,
PARTITION Nov VALUES IN (11) ENGINE = InnoDB,
PARTITION DECM VALUES IN (12) ENGINE = InnoDB) */`
它有大约4.2 GB的数据。我的获取数据的select语句是
SELECT
`status`,
`moddate`
FROM
`xxxxxx`
WHERE
Cname='xxxx'
and ip='0.0.0.0'
and port='3306'
and Variable='xxxxxx'
and status REGEXP '^[0-9]+$|^ON$'
and moddate between '2015-01-01 00:47' and '2015-02-01 01:07';
但需要4:00分钟。自从15天以来我一直在遭遇这个问题。我知道我们需要将索引放在列上。但我不知道如何优化这一点。你能不能请任何人建议我需要索引哪个字段。或分享任何其他链接以优化我的应用程序。感谢名单...
答案 0 :(得分:0)
我会查看where子句并尝试首先确定可能是较小的结果集字段,并将其放在复合索引的第一个位置
您可能有许多条目用于客户端" xxxxx",但在IP地址上设置较小的条目。不确定你的"变量"背景是,也许这个更小。但我会尝试
( IP, port, cname, variable, moddate, status )
但这基本上是ALMOST所有内容的索引。所以,那就是说,我可能会把它砍掉,看看基于...的表现。
( IP, port, cname, moddate )
在考虑更多之后,让CName处于第一位置可能更好......
( CName, IP, port, variable, moddate, status )
因为它击中了我cname可能就像一个网站地址,并且由于单个IP上的服务器可以托管许多网站名称,因此CName将小于整个IP地址。
答案 1 :(得分:0)
这是您的查询:
SELECT status, moddate
FROM xxxxx
WHERE Cname = 'xxxxxx' and
ip = '0.0.0.0' and
port = 3306 and
Variable = 'TABLE_LOCKS_IMMEDIATE' and
status REGEXP '^[0-9]+$|^ON$' and
moddate between '2015-01-01 00:47' and '2015-02-01 01:07';
注意:port
是一个整数,所以我删除了3306
周围的单引号。有时,在某些数据库中,使用混合比较会影响索引的使用(尽管在这种情况下可能不会)。
您的查询正在访问一个表,因此从定义索引开始的地方是WHERE
子句。包含表中提到的所有六列的索引称为“覆盖”索引。覆盖指数通常是表现最好的。
对于这样的索引,从具有相等条件的列开始。然后你得到一个不等式和in
的位置。然后其余的列都在索引中,因此引擎不必访问数据页。因此,最佳索引是xxxxxx(Cname, ip, port, Variable, moddate, status)
。前四列的顺序对于此查询没有不同,因为from
子句中的所有列都具有相等索引。