Есть ряд вопросов по этому вопросу, но мой более конкретно касается вопросов производительности.
Что касается объекта, я хочу отслеживать множество «атрибутов», каждый из которых имеет множестводискретные «значения» (каждый атрибут имеет от 3 до 16 действительных «значений».) Например, рассмотрите возможность отслеживания военного персонала.Атрибуты / значения могут быть (не настоящими, я их полностью составил):
атрибут: {значения}
languages_spoken: {english, spanish, russian, chinese, …. }<br>
certificates: {infantry, airborne, pilot, tank_driver…..}<br>
approved_equipment: {m4, rocket_launcher, shovel, super_secret_radio_thingy….}<br>
approved_operations: {reconnaissance, logistics, invasion, cooking, ….}<br>
awards_won: {medal_honor, purple_heart, ….}
… и т. Д.
Один из способов сделать это - так, как я хочу это сделать - это иметь таблицу персонала и таблицу атрибутов:
personnel table => [id, name, rank, address…..]<br>
personnel_attributes table => [personnel_id, attribute_id, value_id]
вместе со связанными таблицами атрибутов и значений.
Таким образом, если pesonnel_id = 31415 утвержден для логистики, в таблице personal_attributes будет следующая запись:
personnel_id | attribute_id | value_id
31415 | 3 | 2
, где 3 = attribute_id для «одобренных операций» и 2 = value_id для «логистики» (извините, места для форматирования не выстроились.)
Затем поиск, чтобы найти весь персонал, говорящий по-английскиИЛИ испанский, И кто пехотный ИЛИ воздушно-десантный И может управлять лопатой ИЛИ super_secret_radio_thingy будет выглядеть примерно так:
SELECT t1.personnel_id
FROM personnel_attributes t1, personnel_attributes t2, personnel_attributes t3<br>
WHERE ((t1.attribute_id = 1 and t1.value_id = 1) OR (t1.attribute_id = 1 and t1.value_id = 2))<br>
AND ((t2.attribute_id = 2 and t1.value_id = 1) OR (t2.attribute_id = 2 and t1.value_id = 2))<br>
AND ((t3.attribute_id = 3 and t1.value_id = 3) OR (t3.attribute_id = 3 and t1.value_id = 4))<br>
AND t2.personnel_id = t1.personnel_id<br>
AND t3.personnel_id = t1.personnel_id;
Предполагая, что это не совсем глупый способ написания SQLвопрос, проблема в том, что это очень медленно (даже с кажущимсяСоответствующие индексы.)
Так что я играю с использованием побитовых операторов, где каждый атрибут - это столбец в таблице, а каждое значение - бит.Тот же поиск будет выглядеть так:
SELECT personnel_id FROM personnel_attributes<br>
WHERE language & b'00000011'<br>
AND certificates & b'00000011'<br>
AND approved_operations & b'00001100';
Я знаю, что при этом выполняется полное сканирование таблицы, но в моих экспериментах с 350 000 человек выборки и 16 атрибутами каждый первый метод занял 20 секунд.тогда как побитовый метод занял 38 миллисекунд!
Я что-то здесь не так делаю?Это ожидаемые результаты производительности?
Спасибо!