需要有关如何索引和优化特定MySQL数据库的建议

时间:2014-10-20 22:16:37

标签: mysql indexing query-optimization

我正在尝试优化我的MySQL数据库,以便我可以尽快查询它。

它是这样的:

我的数据库由1个表(现在)约1800万行组成 - 并且迅速增长。 此表包含以下列:idx,time,tag_id,x,y,z。 没有列具有任何空值。

'idx'是INT(11)索引列,AI和PK。现在它按升序排列。

'time'是日期时间列。它也在提升。表中50%的'时间'值是不同的(其余值最多可能出现两次或三次)。

'tag_id'是INT(11)列。它没有以任何方式排序,并且有30-100种不同的tag_id值分布在整个数据库中。它也是另一个表的外键。

INSERT - 每隔2-3秒就会在表中插入一个新行。 'idx'由服务器(AI)计算。由于'time'列表示插入行的时间,因此插入的每个新'时间'将高于或等于前一行。所有其他列值都没有任何顺序。

SELECT - 这是一个典型查询的示例: “从表中选择x,y,z,时间,”2014-08-01“和”2014-10-01“之间的日期(时间)和tag_id = 123456”

所以,'time'和'tag_id'是where部分中出现的唯一列,并且它们都将始终出现在每个查询的where部分中。 'x','y'和'z'以及'time'将始终出现在选择部分中。 'tag_id'有时也可能出现在选择部分中。

查询通常会寻求更高(更近)的时间,而不是更旧的时间。含义 - 表中的后续行将被更多地搜索。

INDEXES- 现在,作为PK的'idx'是聚集的ASC索引。 'time'也有一个非聚集的ASC索引。

就是这样。考虑到所有这些数据,典型的查询将在30秒左右为我返回结果。我正试图降低这个时间。任何建议??

我正在考虑将一个或两个索引从ASC更改为DESC(因为较高的值在搜索中更受欢迎)。如果我将'idx'更改为DESC,它将物理反转整个表。如果我将'time'更改为DESC,它将反转'time'索引树。但由于这是一个1800万行表,这样的更改可能需要很长时间才能完成,所以我想确定这是一个好主意。问题是,如果我反转顺序并插入一个新行,服务器是否会知道将它快速放入表的开头?或者它每次都会在这个地方搜索?并且会在表格的开头添加一个新行意味着每次都需要对整个表格进行某种数据转换?

或许我只需要一种不同的索引技术? 你有任何想法都非常欢迎..谢谢!!

1 个答案:

答案 0 :(得分:1)

select x, y, z, time from table 
where date(time) between '2014-08-01' and '2014-10-01' and tag_id = 123456

将列放在像date(time)这样的函数调用中会破坏为该列使用索引的任何机会。如果要使用索引,则必须仅使用裸列进行比较。

因此,如果您想将其与日期进行比较,则应存储DATE列。如果您有DATETIME列,则可能需要使用以下搜索字词:

WHERE `time` >= '2014-08-01 00:00:00 AND `time` < '2014-10-02 00:00:00' ...

此外,您应该尽可能使用多列索引。首先使用在相等条件中使用的列,然后在范围条件中使用一列。有关此规则的更多信息,请参阅我的演示文稿How to Design Indexes, Really

您还可以从添加不用于搜索的列中受益,以便查询可以单独从索引条目中检索列。将这些列放在用于搜索或排序的列之后。这称为仅索引查询。

因此,对于此查询,您的索引应为:

ALTER TABLE `this_table` ADD INDEX (tag_id, `time`, x, y, z);

关于ASC与DESC,语法支持不同方向索引的选项,但在MySQL,InnoDB和MyISAM中使用的两个最流行的存储引擎中,没有区别。排序方向可以或多或少地使用任何一种类型的索引。