【发布时间】:2023-03-10 19:49:01
【问题描述】:
关于这个主题有很多问题,但我的问题更具体的是性能问题。
关于一个对象,我想跟踪多个“属性”,每个“属性”都有多个离散“值”(每个属性都有 3 到 16 个有效“值”。)例如,考虑跟踪军事人员.属性/值可能是(不是真实的,我完全编造了这些):
属性:{values}languages_spoken: {english, spanish, russian, chinese, …. }
certificates: {infantry, airborne, pilot, tank_driver…..}
approved_equipment: {m4, rocket_launcher, shovel, super_secret_radio_thingy….}
approved_operations: {reconnaissance, logistics, invasion, cooking, ….}
awards_won: {medal_honor, purple_heart, ….}
……等等。
这样做的一个方法 - 我想要这样做的方式 - 是有一个人员表和一个属性表:
personnel table => [id, name, rank, address…..]
personnel_attributes table => [personnel_id, attribute_id, value_id]
连同相关的属性和值表。
因此,如果 pesonnel_id=31415 被批准用于后勤,则 person_attributes 表中将有以下条目:
personnel_id | attribute_id | value_id31415 | 3 | 2
其中 3 = attribute_id 表示“approved_operations”,2 = value_id 表示“logistics”(抱歉,格式空间未对齐。)
然后搜索所有会说英语或西班牙语、步兵或空降兵、并且可以操作铲子或 super_secret_radio_thingy 的人员将类似于:
SELECT t1.personnel_id
FROM personnel_attributes t1, personnel_attributes t2, personnel_attributes t3
WHERE ((t1.attribute_id = 1 and t1.value_id = 1) OR (t1.attribute_id = 1 and t1.value_id = 2))
AND ((t2.attribute_id = 2 and t1.value_id = 1) OR (t2.attribute_id = 2 and t1.value_id = 2))
AND ((t3.attribute_id = 3 and t1.value_id = 3) OR (t3.attribute_id = 3 and t1.value_id = 4))
AND t2.personnel_id = t1.personnel_id
AND t3.personnel_id = t1.personnel_id;
假设这不是编写 SQL 查询的完全愚蠢的方法,问题是它非常慢(即使有看似相关的索引。)
所以我正在玩弄按位运算符,其中每个属性都是表中的一列,每个值都是一点。相同的搜索是:
SELECT personnel_id FROM personnel_attributes
WHERE language & b'00000011'
AND certificates & b'00000011'
AND approved_operations & b'00001100';
我知道这会进行全表扫描,但在我对 350,000 个样本人员和每个 16 个属性的实验中,第一种方法需要 20 秒,而按位方法需要 38 毫秒!
我在这里做错了吗?这些是我应该期待的性能结果吗?
谢谢!
【问题讨论】:
-
您可能只是看到查询的结果在连续运行时被缓存在内存中。运行
EXPLAIN看看它是否真的不同
标签: mysql sql performance join bit-manipulation