我有一个包含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。
我也为category_label和纬度制作了索引。
我已经像这样查询了
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。
答案 0 :(得分:0)
首先,您应该查看this和this - 我强烈建议您使用它而不是常见的数据类型。
就您当前的架构而言,请考虑在relational.id
和relational.category_id
(2个单独的索引)上添加索引。但从长远来看,它也无济于事。其他有用的东西 - 不要动态计算distance
- 将其缓存在另一个表中,例如,您可以将其编入索引:查询中最昂贵的部分之一是对动态进行分组和后置过滤(因此,慢)字段
并且你真的不需要categories.category_label
的另一个索引 - 你已经有了它的UNIQUE约束,这意味着索引。
您还可以在records
表格上创建覆盖索引,但与修复动态字段操作相比,它不会带来太多提升
答案 1 :(得分:0)
要帮助开始使用categories
,请添加INDEX(category_label)
relational
看起来像是“多对多”映射。 “记录”是多个“类别”,每个“类别”都有很多“记录”吗?如果是这样,则需要多对多。要提高效果,请按照提示here。
则...
改进距离搜索的快捷方法是在WHERE
子句中设置一个“边界框”并使用INDEX(latitude), INDEX(longitude)
。
如果nu
是UNIQUE
,那么您可能应该将其设为PRIMARY KEY
并摆脱id
。 (首先更改Relational
。)
下一个问题是过滤(WHERE
)到达两个表(过滤类别和位置)。这样无法优化。相反,希望查询可以有效地过滤一个表,然后在查看另一个表时进一步细化它。
答案 2 :(得分:0)
谷歌空间索引。它是几何数据的二维索引。