我有一个包含 3 个表的数据库。
CREATE TABLE `records` (
`id` int(6) NOT NULL auto_increment,
`nu` varchar(40) NOT NULL UNIQUE,
`name` varchar(128),
`latitude` float NOT NULL,
`longitude` float NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `categories` (
`category_id` int(11) NOT NULL,
`category_label` varchar(100) NOT NULL UNIQUE,
PRIMARY KEY (`category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `relational` (
`r_id` int(6) NOT NULL auto_increment,
`id` int(6) NOT NULL,
`category_id` int(11) NOT NULL auto_increment,
PRIMARY KEY (`r_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
我还有 2 个外键,category_id 和 id。
我也为类别标签和纬度制作了索引。
我的查询是这样的
SELECT id, name, latitude, longitude, category_label, ( 6371 * acos( cos(
radians('$lat') ) * cos( radians( latitude ) ) * cos( radians( longitude ) -
radians('$lng') ) + sin( radians('$lat') ) * sin( radians( latitude ) ) ) )
AS distance, FROM records JOIN relational ON records.id = relational.id
JOIN categories ON relational.category_id = categories.category_id
WHERE category_label = '$label' GROUP BY distance HAVING (distance <=
'$radius') ORDER BY distance
我的问题是我有一个很大的数据库,并且查询运行时间太长。我应该为此查询使用什么索引。实际上我不知道哪种索引可以帮助我计算距离的正确方法。我应该更改索引吗?如何改进我的数据库结构或查询?我正在使用 InnoDB。
最佳答案
首先,您可能应该看一下 this和 this - 我强烈建议在您的情况下使用它而不是常见的数据类型。
就您当前的架构而言,请考虑在 relational.id
和 relational.category_id
(2 个单独的索引)上添加索引。但从长远来看,这也无济于事。其他有帮助的事情 - 不要即时计算距离 - 将其缓存在另一个表中,例如,您可以在其中索引它:查询中最昂贵的部分之一是分组和后处理对动态(因此慢)字段进行过滤
而且您实际上并不需要为 categories.category_label
建立另一个索引 - 您已经对它有了 UNIQUE 约束,这意味着索引。
您还可以在记录
表上创建覆盖索引,但与修复动态字段操作相比,它不会带来太大的提升
关于php - mysql查询优化——索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46368330/