繁体   English   中英

如何避免全表扫描

[英]How to avoid full table scan

我有一个大约50GB大小的MYSQL数据库,具有数百万行。 这是我的表结构

CREATE TABLE `logs` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`mac` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`firstTime` datetime DEFAULT NULL,
`lastTime` datetime DEFAULT NULL,
`locid` int(11) DEFAULT NULL,
`client_id` int(11) DEFAULT NULL,
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
`isOut` tinyint(1) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `index_logs_on_location_id` (`location_id`),
KEY `index_logs_on_client_id` (`client_id`),
KEY `macID` (`macID`)
) ENGINE=InnoDB AUTO_INCREMENT=39537721 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

我一直在寻找避免全表扫描的方法。 我试图为Mac列添加索引。 但是,当我在查询上运行EXPLAIN时,当我在WHERE子句中不使用client_id时,possible_keys和key始终为NULL,否则,我唯一使用的索引是client_id或location_id,从某种意义上说,它们对查询没有重大影响执行时间处理时间。 我主要使用这些类型的查询(分组,排序等)。

SELECT mac,COUNT(mac),DATE(lastTime)
FROM logs
WHERE client_id = 1
GROUP BY mac,DATE(lastTime)

考虑这种类型的表结构时,如何优化表以更快地执行查询? 我愿意接受所有建议。 谢谢

使MySQL(或Oracle,SQL Server,Postgres,MariaDB,DB2等)使用索引取决于mac列中数据的唯一性以及唯一性的分布方式。 提到的数据库引擎使用基于成本的优化器,该优化器估计某个解决方案的成本并以最低的成本执行该解决方案。 有时它们是不正确的。 可以通过使用数据库参数来影响此估计,但是这可能会对其他查询产生意外的副作用。

影响结果的第二种方法是更改​​数据结构。

第三种方式,最可行的方法是通过提供提示来影响执行计划。 为此,假设在maclastTime上存在索引,以便db引擎只需要加载此索引即可完成其工作:

CREATE INDEX idx_mac_nn_1 ON logs(mac,lastTime);

假定要进行优化查询(因此您的版本没有client_id列)

SELECT mac,COUNT(mac),DATE(lastTime)
FROM logs FORCE INDEX idx_mac_nn_1
GROUP BY mac,DATE(lastTime);

然后,这将强制MySQL无论如何使用索引。

对于此查询:

SELECT mac, COUNT(mac), DATE(lastTime)
FROM logs
WHERE client_id = 1
GROUP BY mac, DATE(lastTime)

您要在(client_id, mac, lastTime)上建立索引。 如果您不介意所需的额外空间,我建议使用覆盖索引。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM