【发布时间】:2014-08-16 05:53:33
【问题描述】:
我有下表:
create table x (
id integer,
property integer
);
我需要高效地运行查询来测试给定 ID 的多个属性值。例如,我可能想要一个查询来获取所有具有满足条件的属性的 id:1 而不是(2 或 3 或 4 或 5)。
如果我的所有属性都在布尔列中('t1' = true 如果属性值 1 存在 id,否则为 false 等),那么我可以简单地运行这个非常快速的查询(假设 y 是这样一个表):
select * from y where t1 and not (t2 or t3 or t4 or t5);
不幸的是,我有数千个属性,所以这行不通。此外,查询没有押韵或理由,因此虽然我可以将属性组捆绑到概念关系中,但查询边界不尊重这一点。此外,这些查询是(间接)由用户确定的,因此在预期中创建视图将无济于事。最后,我们将不断添加具有新属性的数据集,其关系可能是新的、模糊的或交叉的,这意味着尝试创建关系表可能会成为维护的噩梦。
因此我选择了原始模式。
为了完成我的查询,我首先尝试在查询中涉及的字段上创建一个数据透视,然后进行查询:
create table pivot as (
select
id,
max(if(property=1,true,false)) as 't1',
max(if(property=2,true,false)) as 't2',
max(if(property=3,true,false)) as 't3',
max(if(property=4,true,false)) as 't4',
max(if(property=5,true,false)) as 't5'
from x);
select * from pivot where t1 and not (t2 or t3 or t4 or t5);
但是,这非常慢。事实上,它比未经优化的自制解决方案要慢。
我知道我可以生成带有子查询的复杂查询,但有限的测试表明性能会更差(除非我的查询结构不正确)。
我可以做些什么来加快查询速度?
【问题讨论】:
-
是什么让你觉得巨大太大了?
-
它太大了,因为它 > MySQL 的最大列数 (4,096)。将数据拆分为多个表可以解决这个问题,但代价是查询多个表——可能有数千个表。
-
表格中有哪些行?据推测,布尔值是根据其他信息计算得出的,因此可能有一种方法可以对整个表进行不同的编码。
-
@philipxy -- 我不明白您所说的“表格中有哪些行?”是什么意思。计算的布尔值很少。绝大多数是测量的。所以每个属性都是一个测量 ID。
-
实测:好的。关于“表中有哪些行?”:有些行是表,有些则不是。对于与标题匹配的每个基表行,我们决定它是否进入。例如,Employee(i,n,a) 是“员工 [i] 的姓名为 [n] 并居住在 [a]”的行。它们“满足”了“关系”的“特征谓词”。特征谓词通常就是我们所说的表格的“意义”。我可以说,你能规范化布尔表吗?规范化表正在从特征谓词中删除 AND。
标签: mysql database normalization database-normalization