我有两个MySQL查询,用于帮助我在我的网站上安排新闻。这里指出的所有字段都是数字(int或tinyint),并且都有一个索引。有人可以帮我构建多列索引,这会加速两个查询吗?
SELECT MAX(content_time) AS content_time
FROM cm_data
WHERE content_time < UNIX_TIMESTAMP()
AND page = '1'
AND (content_type = '1' OR content_type = '5')
SELECT content_id
FROM cm_data
WHERE (content_time < UNIX_TIMESTAMP()
OR (hp_time >= UNIX_TIMESTAMP() AND content_time < UNIX_TIMESTAMP()
)
)
AND page = '1'
AND (content_type = '1' OR content_type = '5')
ORDER BY hp_time DESC
, content_time DESC
LIMIT 20
这是数据库架构:
CREATE TABLE IF NOT EXISTS `cm_data` (
`content_id` mediumint(8) NOT NULL AUTO_INCREMENT,
`content_time` int(11) DEFAULT NULL,
`hp_time` int(11) NOT NULL DEFAULT '0',
`content_type` tinyint(2) DEFAULT NULL,
`page` tinyint(2) NOT NULL DEFAULT '1',
PRIMARY KEY (`content_id`),
KEY `content_time` (`content_time`),
KEY `content_type` (`content_type`),
KEY `page` (`page`),
);
答案 0 :(得分:1)
索引并不总是答案(尤其是在预期会有许多INSERT
语句的情况下)。话虽如此,您可以采取一些措施来优化这些查询:
1)确保您的约束正确形成。在第二个查询中,您基本上具有Case1 OR ( Case2 AND Case1 )
,可以简化为Case1
(布尔代数)。在查询优化器查看它之前确保尽可能减少,这不仅可以减少优化器所需的工作量,还可以捕获无法解析的情况。
2)检查约束的顺序。由于它没有在文档中的任何地方声明查询优化器将以任何特定顺序检查非唯一键的约束,因此可以使用一些优化知识来加速查询。一般而言,非整数约束的评估将是昂贵的(STRING等)。在您的情况下,UNIX_TIMESTAMP()返回UNSIGNED INT,而该字段被指定为INTEGER。这将导致每行的转换操作,这将是昂贵的。因此,如果您可以减少必须进行比较的次数(通过首先过滤出具有更简单约束的行),则必须执行的操作更少,从而缩短执行时间。
2a)MySQL不支持函数索引,因此您可以将字段的数据类型更改为UNSIGNED INT(首选,如果可用),或者创建一个附加列,该列使用包含UNSIGNED INT等效项的触发器进行更新该字段,并索引它。后者并不理想,但可以通过增加表格大小来提高性能。