我有一个用于存储统计数据的表。目前,这一行在一天结束时填充了大约1000万行,然后复制到每日统计表并删除。出于这个原因,我无法使用自动递增的主键。
这是表结构:
CREATE TABLE `stats` (
`shop_id` int(11) NOT NULL,
`title` varchar(255) CHARACTER SET latin1 NOT NULL,
`created` datetime NOT NULL,
`mobile` tinyint(1) NOT NULL DEFAULT '0',
`click` tinyint(1) NOT NULL DEFAULT '0',
`conversion` tinyint(1) NOT NULL DEFAULT '0',
`ip` varchar(20) CHARACTER SET latin1 NOT NULL,
KEY `shop_id` (`shop_id`,`created`,`ip`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
我在shop_id, created, ip
上有一个密钥,但我不确定应该使用哪些列来创建最佳索引以进一步提高查找速度?
下面的查询在没有密钥的情况下大约需要12秒,使用上面的索引大约需要1.5秒:
SELECT DATE(CONVERT_TZ(`created`, 'UTC', 'Australia/Brisbane')) AS `date`, COUNT(*) AS `views`
FROM `stats`
WHERE `created` <= '2017-07-18 09:59:59'
AND `shop_id` = '17515021'
AND `click` != 1
AND `conversion` != 1
GROUP BY DATE(CONVERT_TZ(`created`, 'UTC', 'Australia/Brisbane'))
ORDER BY DATE(CONVERT_TZ(`created`, 'UTC', 'Australia/Brisbane'));
答案 0 :(得分:1)
AUTO_INCREMENT id
。不要担心截断/删除。 (但是,如果ID未重置,您可能需要使用BIGINT
,而不是INT UNSIGNED
以避免溢出。)id
作为主键,而是使用PRIMARY KEY(shop_id, created, id), INDEX(id)
。id
的加法)。 INDEX(id)
旨在让AUTO_INCREMENT
满意。 (每小时或每天DELETE
是一个单独的问题。)!= 1
,说= 0
;优化器在=
处比在!=
处好得多。=
,那么这变得可行且更好:INDEX(shop_id, click, conversion, created)
- created
必须是最后一个。毕竟,如果你还有问题,请重新开始讨论;可能会有进一步的调整。
答案 1 :(得分:-1)
在你的where子句中,首先使用列,它将返回一小组结果,依此类推,并以相同的顺序创建索引。
你有
WHERE created <= '2017-07-18 09:59:59'
AND shop_id = '17515021'
AND click != 1
AND conversion != 1
如果创建将返回少量的set作为与其他3列的比较,那么你很好,否则你在where子句中的第一个位置的那个列然后根据相同的解释选择第二列并根据你创建索引where子句。
如果你认为订单没问题,那就创建一个索引
KEY created_shopid_click_conversion (created,shop_id, click, conversion);
。