我有一个包含以下列的表格帖子:
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会非常慢。
更新:我确实需要一周中每一天的列,因为用户设置发布的日期。可能会在几天内同时进行。
答案 0 :(得分:3)
您的架构设计奇怪。您当前的设置可能会让报告变得简单,但您是正确的,像您建议的那样建立索引会产生可怕的insert
和update
效果。
我的建议是重构这张表。我建议您更改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
列上保留一个索引。