【问题标题】:mysql query optimization - indexesmysql查询优化——索引
【发布时间】:2017-09-22 15:34:43
【问题描述】:

我有一个包含 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 和 latitude 创建了索引。 我的查询是这样的

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。

【问题讨论】:

  • 在您的查询上运行EXPLAIN并发布结果。

标签: php mysql indexing latitude-longitude sql-optimization


【解决方案1】:

首先,您可能应该看看thisthis - 我强烈建议您使用它而不是常见的数据类型。

就您当前的架构而言,考虑在relational.idrelational.category_id(2 个单独的索引)上添加索引。但从长远来看,它也无济于事。其他有帮助的事情 - 不要即时计算 distance - 将其缓存在另一个表中,例如,您可以在其中对其进行索引:查询中最昂贵的部分之一是动态分组和后过滤(因此, 慢) 场

而且你真的不需要为categories.category_label 建立另一个索引——你已经对它有 UNIQUE 约束,这意味着索引。

您还可以在 records 表上创建覆盖索引,但与修复动态字段操作相比,它不会带来太大的提升

【讨论】:

  • 感谢您的回答,我会检查一下。但我想问一些关于你说的第一件事可能很愚蠢的事情。我现在可能无法为此数据库更改我的数据库引擎。但如果可以的话,我已经看到 MyISAM 支持空间数据。但是如果我使用它,我就不能使用外键,所以我不能连接我的表的列。我对吗?所以我想这对我来说不会很好。
  • @arek 恐怕你听错了,空间数据类型不是单独的数据库引擎,它的引擎支持列表可以在这里找到:dev.mysql.com/doc/refman/5.7/en/creating-spatial-columns.html
  • @arek 关于外键:1)您不必有外键来连接表。这些用于创建约束 2)为什么需要根据空间数据创建外键?您搜索和/或计算这些数据,但通过某些标识字段连接到其他数据,例如 category_id 或类似的
  • @arek 并没有愚蠢的问题,但那些不问他们的人应该被认为是愚蠢的
【解决方案2】:
  1. 为了帮助您开始使用categories,请添加INDEX(category_label)

  2. relational 看起来像“多对多”映射。是不是多个“类别”中的“记录”,而每个“类别”又有多个“记录”?如果是这样,则需要多对多。为提高性能,请遵循提示here

  3. 那么……

改进距离搜索的快速简便的方法是在WHERE 子句中添加一个“边界框”并添加INDEX(latitude), INDEX(longitude)

如果nuUNIQUE,那么你可能应该让它成为PRIMARY KEY,如果id 则去掉它。 (先换Relational。)

下一个问题是过滤 (WHERE) 正在进入两个表(按类别和位置进行过滤)。这样无法优化。相反,希望查询可以有效地过滤一个表,然后在查看另一个表时进一步细化它。

【讨论】:

    【解决方案3】:

    谷歌空间索引。它是几何数据的二维索引。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-24
      • 2012-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多