0

我有一个需要存储几个位域的 MySQL 表...

  • notification.id -- 自动编号 int
  • Association.id -- BIT FIELD 1 -- 存储一个或多个关联 ID(从另一个表中获取)
  • type.id -- BIT FIELD 2 -- 存储一个或多个应用于此通知的类型(同样,从另一个表中获得)
  • notification.day_of_week -- BIT FIELD 3 -- 存储一周中的一天或多天
  • notification.target -- 发送通知的位置 -- 数据类型无关紧要,因为我们永远不会对该字段进行索引或排序,但可能会存储一个电子邮件地址。

我的用户将能够将他们的通知配置为在一天或多天、一种或多种关联中针对一种或多种类型触发。我需要一种快速、可索引的方式来存储这些数据。

位域 1 和 2 可以扩展为具有比现在更多的值。目前 1 的值高达 125,而 2 的值高达 7,但预计两者都会更高。

位域 3 存储星期几,因此,总是只有 7 个可能的值。

我需要经常(每隔几分钟)运行一个脚本,根据类型、关联和日期扫描此表,以确定是否应该发送给定的通知。查询需要快速,添加新数据越简单越好。我并没有根据需要使用连接、子查询等,但我无法想象这些会更快。

最后一个要求——如果我在这里存储了 1000 个不同的通知,具有 125 种关联可能性、7 种类型和一周中的 7 天,那么如果仅使用整数并存储多个副本,那么记录的组合对我来说太高了该行,而不是使用位字段,因此似乎需要使用位字段。

但是,据我所知,如果我想从一周中的特定日子选择所有内容,比如星期二(可能是位字段中的 b0000100),位字段没有被索引,所以我可以做...

SELECT * FROM \`mydb\`.\`mytable\` WHERE \`notification.day_of_week\` & 4 = 4;

据我了解,这根本不会使用索引。

关于如何以可索引方式执行此操作或类似操作的任何建议?

(我在一个非常标准的 LAMP 堆栈上工作,我正在寻找有关 MySQL 索引如何在这个或类似替代方案上工作的细节。)

谢谢!

4

2 回答 2

0

没有“好”的方法(据我所知)来完成你想要的。请注意,BIT 数据类型的大小限制为 64 位。

对于可以静态定义的位,MySQL 提供了 SET 数据类型,它在某些方面与 BIT 相同,而在其他方面则不同。

例如,对于一周中的几天,您可以定义一个列

dow SET('SUN','MON','TUE','WED','THU','FRI','SAT')

没有内置方法(我知道将内部位表示恢复,但您可以在列中添加 0,或强制转换为无符号,以获得十进制表示。

SELECT dow+0, CONVERT(dow,UNSIGNED), dow, ...

1  1  SUN
2  2  MON
3  3  SUN,MON
4  4  TUE
5  5  SUN,TUE
6  6  MON,TUE
7  7  SUN,MON,TUE

当 SET 列是索引中的前导列时,MySQL 可以使用“覆盖索引”来满足在 SET 列上使用谓词的查询。(即 EXPLAIN 显示 'Using where; Using index')但是 MySQL 可能正在执行索引的完整扫描,而不是执行范围扫描。(而且 MyISAM 引擎和 InnoDB 引擎之间可能存在差异。)

SELECT id FROM notification WHERE FIND_IN_SET('SUN',dow)

SELECT id FROM notification WHERE (dow+0) MOD 2 = 1

但是......这种用法是非标准的,不能真正推荐。一方面,不能保证这种行为,MySQL 可能会在未来的版本中改变这种行为。

于 2012-08-02T21:48:28.893 回答
0

我对此进行了更多研究,并意识到没有办法让索引像我上面概述的那样工作。因此,我创建了一个辅助表(有点像 WordPress 元表格式),用于存储星期几的条目等。我将根据需要加入这些表。幸运的是,我预计目前不会有超过 10,000 个条目,所以它应该足够快地加入。

如果有人有更好的答案,我仍然对更好的答案感兴趣!

于 2012-08-07T13:06:49.953 回答