我是MySQL查询优化的新手,需要有关如何针对两个查询优化数据库的建议 - 我应该设置哪些索引以及在哪里建立。下面是数据库结构和查询。
CREATE TABLE `data_node` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`type` enum('node','place') DEFAULT NULL,
`name` varchar(255) DEFAULT '',
`source_id` bigint(20) unsigned DEFAULT NULL,
`data_id` bigint(20) unsigned NOT NULL,
`data_lat` decimal(8,6) NOT NULL,
`data_lon` decimal(9,6) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `data_node_tag` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`node_id` bigint(20) unsigned NOT NULL,
`data_key` varchar(255) NOT NULL DEFAULT '',
`data_value` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
首先查询:
SELECT *
FROM data_node n
LEFT JOIN data_node_tag nt ON nt.node_id = n.id
WHERE n.type = "place"
AND nt.data_value LIKE "%place%"
GROUP BY n.data_id LIMIT 100
第二次查询:
SELECT *
FROM data_node n
LEFT JOIN data_node_tag nt ON nt.node_id = n.id
WHERE n.source_id = 123
AND n.type = "node"
AND nt.data_value = "cafe"
AND (n.data_lat BETWEEN 1.000000 AND 2.000000)
AND (n.data_lon BETWEEN 3.000000 AND 4.000000)
GROUP BY n.data_id LIMIT 1000
我将非常感谢你的帮助。
答案 0 :(得分:0)
索引:
data_node_tag.node_id
data_node.source_id
data_node.type
data_node_tag.data_value
data_node.lat
data_node.lon。
引擎将根据基数选择要使用的引擎。你可以做得更少,但这取决于你的数据是什么样的。
其次,您应该索引where子句中使用的任何字段。 唯一的任何字段都应具有唯一索引。您还可以在多个字段上创建复合索引,但从每个字段的索引开始。
数据库引擎每个查询每个表只能使用1个索引(实际上是每个别名,但不要担心)所以如果你有2个字段要查询,你可以在两个字段上创建一个复合索引。那些composite index
答案 1 :(得分:0)
对于第一个查询,您需要data_node(type, id, data_id)
和data_node_tag(node_id, data_value)
上的索引。
对于第二个查询,您需要data_node(source_id, type, data_lat, data_long, id)
和data_node_tag(id, data_value)
上的索引(这与第一个查询相同)。
答案 2 :(得分:0)
以下是对query1的建议:
注意:最重要的索引在node_id字段上,因为您要根据它连接两个表。因此,您只能通过此索引获得主要的性能差异。
进一步优化查询1& 2它将取决于根据不同条件过滤的数据量。
答案 3 :(得分:0)
将 data_node_tag 表的外键用于 id 字段。 由于您有重复的 id 字段。您可以使用外键来克服重复数据。
CREATE TABLE data_node_tag (
id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
node_id bigint(20) unsigned NOT NULL,
data_key varchar(255) NOT NULL DEFAULT '',
data_value varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (id),
FOREIGN KEY (id) REFERENCES data_node(id)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
答案 4 :(得分:0)
(这些评论更多的是警告而不是答案。)
data_node_tag
,摆脱id
;更改为PRIMARY KEY(node_id, data_key)
。即便如此,你最终还是会发现为什么EAV架构很糟糕。
您还将了解为什么lat / lng难以优化。
使用InnoDB,而不是MyISAM。
无法优化 LIKE "%place%"
(尽管LIKE "place%"
可以使用索引)。考虑FULLTEXT
。