使用许多列索引MYSQL表

时间:2017-07-07 06:48:23

标签: mysql indexing

我有一个包含以下列的表格帖子:
start_at, sun, mon, tue, wen, thu, fri, sat

start_at是日期类型,其他是 - tinyint。

我按以下方式进行查询:

SELECT * FROM posts WHERE start_at >= '2017-02-01' AND mon = 1

那是在第二个AND之后我动态地设置了适当的星期几。

索引此表的最佳方法是什么?我是否需要为一周中的每一天制作综合索引,例如:

CREATE INDEX mon_index ON posts(start_at,mon);
CREATE INDEX sun_index ON posts(start_at,sun);

如果我为一周中的每一天创建7个索引,我认为INSERT和UPDATE会非常慢。

更新:我确实需要一周中每一天的列,因为用户设置发布的日期。可能会在几天内同时进行。

3 个答案:

答案 0 :(得分:3)

您的架构设计奇怪。您当前的设置可能会让报告变得简单,但您是正确的,像您建议的那样建立索引会产生可怕的insertupdate效果。

我的建议是重构这张表。我建议您更改posts表以包含列(start_at,day),而不是当前的设置。在这个设计中,日可以是从周日到周六,你只需要一个索引(start_at, day)

如果你真的需要当前的格式来阅读/报告(我不会责怪你),你总是可以设置一个以这种方式转动数据的视图。

所有这些都说明,并非您在上符合资格的每个字段都需要在索引中。我的估计是,你的表格的绝大部分行都可以按日期过滤。剩下的几个可能不会需要被索引以获得良好的读取性能。

另一方面,为什么甚至存储这一天?这可以根据日期计算。

答案 1 :(得分:0)

如另一个人所说,可能仅为start_at索引就足够了。

如果您想调查包含发布日的索引(特别是如果您的表有很多字段,并且您只想列出字段start_at和发布日),则可以创建如下表:< / p>

CREATE TABLE XX (start_at ..., which_day tinyint UNSIGNED);

和像这样的索引

CREATE INDEX XX_IX01 (start_at, which_day);

where_day可以使用某种编码:

0 =没有一天 2 ^ 0 =太阳 2 ^ 1 =问 2 ^ 2 = .. ... 2 ^ 6 =坐在

因此,例如,如果mon和sat为1,则值应为2 ^ 1 + 2 ^ 6 = 2 + 64 = 66。

如果可能,请避免SELECT *并写下您需要的字段。

使用EXPLAIN检查db引擎如何使用索引/表。

此链接可能很有用:How can I index these queries?

示例数据:

CREATE table et1 (start_at DATE, which_day tinyint UNSIGNED);
CREATE INDEX ET1_IX1 ON et1(start_at, which_day);

INSERT INTO et1 VALUES ('20170701', 132);
INSERT INTO et1 VALUES ('20170702', 3);
INSERT INTO et1 VALUES ('20170704', 5);
INSERT INTO et1 VALUES ('20170630', 2);


SELECT start_at, which_day, which_day & 128 AS X FROM et1;
SELECT start_at, which_day, which_day & 128 AS X FROM et1 WHERE start_at>'20170630' AND which_day & 128 =128;
EXPLAIN SELECT * FROM et1 WHERE start_at>'20170630' AND which_day & 128 =128;

DROP table et1;

答案 2 :(得分:0)

您的数据库架构过于复杂,无需添加所有这些列,也无需创建大量索引。

您可以将帖子简化为:

id | title | (...) | start_at

然后您可以替换此查询:

SELECT * FROM posts WHERE start_at >= '2017-02-01' AND mon = 1

而是使用DAYOFWEEK函数:

SELECT * FROM posts WHERE start_at >= '2017-02-01' AND DAYOFWEEK(start_at) = 2

(1 =星期日,2 =星期一,......,7 =星期六)。

然后,您可以在start_at列上保留一个索引。