Поскольку структура базы данных не была разработана с учетом реалий RDBM (вероятно, это не ваше дело, я просто должен все равно указать на это ...), производительность всегда будет низкой, хотя можно написать запрос, который закончу.
Джим прав в том, что запрос приводит к декартовому произведению. Если этот запрос будет возвращен без группировки и без фильтрации, вы можете ожидать (SELECT POW(COUNT(*), 2) FROM data)
результатов. Кроме того, любая форма внешнего объединения не является необходимой, поэтому здесь вам нужно стандартное внутреннее объединение (не то, чтобы это могло иметь значение с точки зрения производительности, это просто более уместно).
Также необходимо другое условие объединения, t1.id != t2.id
, чтобы каждая запись не соответствовала самой себе.
SELECT t1.id, t1.name
FROM data t1
JOIN data t2
ON t1.name = t2.name
AND t1.id != t2.id //
WHERE CONV(t1.mask, 2, 10) & CONV(t2.mask, 2, 10) > 0
GROUP BY t1.name
HAVING COUNT(*) > 1;
Ваш неполный запрос:
SELECT t1.id, t1.name, t1.mask
FROM data t1
WHERE t1.name IN (SELECT t2.name FROM data t2 GROUP BY t2.name HAVING COUNT(*) > 1);
SELECT t1.id, t1.name, t1.mask
FROM data t1
WHERE EXISTS (SELECT 1 FROM data t2 WHERE t2.name = t1.name GROUP BY t2.name HAVING COUNT(*) > 1);
От головы до головы, я не могу сказать вам, какой из них будет лучше. Если data.name
проиндексирован (и я надеюсь, что это так), то стоимость любого запроса должна быть довольно низкой. Первый будет кэшировать копию подвыбора, тогда как второй будет выполнять несколько запросов к индексу.
Одной из самых основных оптимизаций (при условии, что структура таблицы остается неизменной) будет преобразование поля маски в тип данных целых чисел без знака, что позволит сохранить множество вызовов в CONV()
.
WHERE CONV(t1.mask, 2, 10) & CONV(t2.mask, 2, 10) > 0
становится
WHERE t1.mask & t2.mask > 0
Конечно, разбивать данные дальше имеет смысл. Вместо того, чтобы хранить битовую маску в одной записи, разбейте все эти биты на отдельные записи
id name mask
== ==== ====
11 alpha 1101
станет
id name value
== ==== =====
11 alpha 1
12 alpha 4
13 alpha 8
Теперь стратегически размещенный индекс на name
и value
превращает запрос в кусок пирога
SELECT name, value
FROM data
GROUP BY name, value
HAVING COUNT(*) > 1;
Надеюсь, это поможет.