我在索引此查询时遇到问题:
SELECT *,
(ROUND(SQRT(
POW(LEAST(ABS(-12 - wdata.x),
ABS(401 - ABS(-12 - wdata.x))), 2) +
POW(LEAST(ABS(45 - wdata.y),
ABS(401 - ABS(45 - wdata.y))), 2)),3)
) AS distance
FROM odata
LEFT JOIN wdata ON wdata.id=odata.vref
WHERE TRUE
HAVING distance<4.9497474683058326708059105347339
ORDER BY distance
LIMIT 30
结果是:
+----+-------------+-------+--------+---------------+---------+---------+-----------------------------+-------+---------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+--------+---------------+---------+---------+-----------------------------+-------+---------------------------------+ | 1 | SIMPLE | odata | ALL | NULL | NULL | NULL | NULL | 19118 | Using temporary; Using filesort | | 1 | SIMPLE | wdata | eq_ref | PRIMARY | PRIMARY | 4 | mytravia_1000-14.odata.vref | 1 | NULL | +----+-------------+-------+--------+---------------+---------+---------+-----------------------------+-------+---------------------------------+ 2 rows in set (0.00 sec)
我知道它显示0.00秒是执行时间,但此查询将运行多次,它显示它会减慢我的数据库,我不知道为什么!
每次我看到行检查是459448这个查询,所以它在某些原因对我的工作相当糟糕。
有人能给个建议吗?我如何为odata表制作合适的索引?或者我可以使用子查询来修复它?
这些表是:
解释odata:
vref int(10) unsigned NO PRI NULL type tinyint(4) NO NULL conqured mediumint(8) unsigned NO NULL wood float(12,2) NO NULL iron float(12,2) NO NULL clay float(12,2) NO NULL woodp float(12,2) NO NULL ironp float(12,2) NO NULL clayp float(12,2) NO NULL maxstore mediumint(8) unsigned NO NULL crop float(12,2) NO NULL cropp float(12,2) NO NULL maxcrop mediumint(8) unsigned NO NULL lasttrain int(10) unsigned NO NULL lastfarmed int(10) unsigned NO NULL lastupdated int(10) unsigned NO NULL loyalty tinyint(4) NO 100 owner smallint(5) unsigned NO 2 name char(45) NO Oasis
并解释 wdata:
id int(10) unsigned NO PRI NULL auto_increment fieldtype tinyint(3) NO NULL oasistype tinyint(3) NO NULL x smallint(5) NO MUL NULL y smallint(5) NO MUL NULL occupied tinyint(4) NO NULL image char(12) NO MUL NULL pos tinyint(3) NO MUL NULL
不得不说wdata.id和odata.vref已经被索引了!
表格结构-
CREATE TABLE IF NOT EXISTS `odata` ( `vref` int(10) unsigned NOT NULL, `type` tinyint(4) NOT NULL, `conqured` mediumint(8) unsigned NOT NULL, `wood` float(12,2) NOT NULL, `iron` float(12,2) NOT NULL, `clay` float(12,2) NOT NULL, `woodp` float(12,2) NOT NULL, `ironp` float(12,2) NOT NULL, `clayp` float(12,2) NOT NULL, `maxstore` mediumint(8) unsigned NOT NULL, `crop` float(12,2) NOT NULL, `cropp` float(12,2) NOT NULL, `maxcrop` mediumint(8) unsigned NOT NULL, `lasttrain` int(10) unsigned NOT NULL, `lastfarmed` int(10) unsigned NOT NULL, `lastupdated` int(10) unsigned NOT NULL, `loyalty` tinyint(4) NOT NULL DEFAULT '100', `owner` smallint(5) unsigned NOT NULL DEFAULT '2', `name` char(45) NOT NULL DEFAULT 'Unoccupied Oasis', PRIMARY KEY (`vref`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
对于 wdata 是 -
CREATE TABLE IF NOT EXISTS `wdata` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `fieldtype` tinyint(3) NOT NULL, `oasistype` tinyint(3) NOT NULL, `x` smallint(5) NOT NULL, `y` smallint(5) NOT NULL, `occupied` tinyint(4) NOT NULL, `image` char(12) NOT NULL, `pos` tinyint(3) NOT NULL, PRIMARY KEY (`id`), KEY `x` (`x`), KEY `y` (`y`), KEY `image` (`image`), KEY `pos` (`pos`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=160802 ;
顺致敬意,
正如瑞克·詹姆斯所说,你不能索引< code >距离,因为它是动态计算的。
这就给你出了两个问题:1,它慢,你也知道。第二,你在数据层做逻辑计算,这是我不喜欢的。
我认为这里最好的解决方案是不要像你正在做的那样计算飞行距离。为什么不在插入/更新 x
和/或 y 的同时将距离存储在 wdata
中呢
?将其放在名为“距离
”的列中。然后,您可以为该列编制索引,一切都将非常快。此外,您不会一遍又一遍地重做计算,从而使事情变得更有效率。最后,您将能够删除数据层的计算,并将其放在应用程序级别的更合适的位置。
CREATE TABLE IF NOT EXISTS `wdata` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`fieldtype` tinyint(3) NOT NULL,
`oasistype` tinyint(3) NOT NULL,
`x` smallint(5) NOT NULL,
`y` smallint(5) NOT NULL,
`distance` decimal(32, 24) NOT NULL,
`occupied` tinyint(4) NOT NULL,
`image` char(12) NOT NULL,
`pos` tinyint(3) NOT NULL,
PRIMARY KEY (`id`),
KEY `x` (`x`),
KEY `y` (`y`),
KEY `distance` (`distance`),
KEY `image` (`image`),
KEY `pos` (`pos`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=160802;
(距离的数据类型可以是您认为合适的任何数据类型。我使用了 decimal(32, 24),
它将存储最多 24 位在小数点右边和最多 12 个位置的数字。根据需要进行调整。
然后,您可以将插入内容更改为如下所示:
(示例数据:
)
insert into wdata (fieldtype,oasistype,x,y,distance,occupied, image, pos)
values (1, 1, 10, 11, (ROUND(SQRT(
POW(LEAST(ABS(-12 - 10),
ABS(401 - ABS(-12 - 10))), 2) +
POW(LEAST(ABS(45 - 11),
ABS(401 - ABS(45 - 11))), 2)),3)
), 1, 'abcdefghijkl', 1)
您的select语句将是:
SELECT * FROM odata
LEFT JOIN wdata ON wdata.id=odata.vref
where wdata.distance<4.9497474683058326708059105347339
ORDER BY wdata.distance
LIMIT 30
如果wdata表中已经有一组数据,并且无法重新插入,则可以执行此操作,一次更新所有行(在添加新的距离列后):
update wdata set distance =
(ROUND(SQRT(
POW(LEAST(ABS(-12 - x),
ABS(401 - ABS(-12 - x))), 2) +
POW(LEAST(ABS(45 - y),
ABS(401 - ABS(45 - y))), 2)),3))
另外值得注意的是,我会从MySQL中删除数学运算,让你的应用程序去做。
例如,在PHP中:
$distance = (round(sqrt(pow(min(abs(-12 - 10), abs(401 - abs(-12 - 10))), 2) + pow(min(abs(45 - 11), abs(401 - abs(45 - 11))), 2)),3));
$sql = "insert into wdata (fieldtype, oasistype, x, y, distance, occupied, image, pos)
values (1, 1, 10, 11, $distance, 1, 'abcdefghijkl', 1)";
目前没有索引可以加快查询速度。它当前必须为 JOIN 化两个
表的结果中的每一行计算该 SQRT
。
在执行任何< code > join 操作之前,先找到closes 30,您会得到一些改进:
SELECT *, distance
FROM ( SELECT id,
(ROUND(SQRT(
POW(LEAST(ABS(-12 - wdata.x),
ABS(401 - ABS(-12 - wdata.x))), 2) +
POW(LEAST(ABS(45 - wdata.y),
ABS(401 - ABS(45 - wdata.y))), 2)),3)
) AS distance
FROM wdata
HAVING distance<4.9497474683058326708059105347339
ORDER BY distance
LIMIT 30
) w
JOIN odata ON w.id=odata.vref
ORDER BY w.distance
这将需要id和vref索引。
下一个改进是将搜索限制在至少一个方向:
AND x >= -12 - 4.94...
AND x <= -12 + 4.94...
并在wdata
中具有复合索引index(x,id)
。(对不起,我不知道“401”在公式中的位置。)
如果这还不够快,解决方案会变得更加复杂。
问题内容: 在这里很难说出要问什么。这个问题是模棱两可,含糊不清,不完整,过于宽泛或夸张的,不能以目前的形式合理地回答。如需帮助澄清此问题以便可以重新打开, 请访问帮助中心。 8年前关闭。 有一个查询运行得比我想要的慢,但是我无法共享详细信息。该查询已经返回了正确的结果,并且已经对其进行了重构,但是我无法使其足够快地运行。谓词在可能的情况下已经是可Sarg- able 的。它已经正确地使用了联接,
嗨,如何检查聚合查询中使用的索引和扫描对象的数量,类似于db.collection.find().explain()?
问题内容: 今天,我遇到了一个有趣的SQL问题,尽管我想出了一个行之有效的解决方案,但我怀疑这是最佳还是最有效的答案。在这里,我请专家- 帮助我学习一些知识并改善查询条件!RDBMS是SQL Server 2008 R2,查询是SSRS报告的一部分,该报告将针对约100,000行运行。 本质上,我有一个ID列表,该ID可能具有多个与之关联的值,这些值是Yes,No或其他字符串。对于ID x,如果任
问题内容: 有没有办法列出所有SQL Server CE数据库表索引,或者至少列出单个表? 问题答案: -检索有关数据库中包含的索引的信息。选择*从INFORMATION_SCHEMA.INDEXES -检索数据库中的所有表,包括系统表。选择*从INFORMATION_SCHEMA.TABLES Arjuna Chiththananda-检索SQL CE数据库的架构信息
问题内容: 我有此查询,它运行良好 从此查询中,我从我的位置(这是我的第一张表)中选择所有3 KM的餐厅。 但是我需要从3Km中的食品接头中选择AVG等级。 该查询也运行完美: 但是我需要添加这两个查询,通过它们我可以选择所有那些食品接头及其等级AVG。 问题答案: 只需放置子查询,您将得到结果:
现在,我要检索一个值: Q1:在[3.3,6.6]范围内-预期返回值:[3.3,5.5,6.6]或[3.3,3.3,5.5,6.6](包括最后一个),如果没有,则为[3.3,5.5]或[3.3,3.3,5.5]。 Q2:在[2.0,4.0]范围内-预期返回值:[3.3]或[3.3,3.3] 对于任何其他多索引维度都是相同的,例如B值: Q3:在范围[111,500]中有重复,作为范围中的数据行数-