Mysql не существует или альтернатива - PullRequest
0 голосов
/ 06 сентября 2018

Пример таблицы, данные вместе с запросом можно найти в http://sqlfiddle.com/#!9/2e65dd/3

Я заинтересован в поиске всех различных идентификаторов user_id, которые не имеют определенного типа record_.

В моем случае эта таблица огромна, в ней несколько миллионов записей и индекс по столбцу user_id. Хотя я планирую получать его партиями, ограничивая вывод до 1000 за раз.

select distinct user_id from 
records o where 
not exists (
    select * 
    from records i 
    where i.user_id=o.user_id and i.record_type=3) 
limit 0, 1000

Есть ли лучший подход для достижения этой потребности?

Ответы [ 3 ]

0 голосов
/ 06 сентября 2018

Вы можете создать временную таблицу с типами записей, равными 3, например

Select distinct user_id
into #users
from records
where record_type=3 

Затем создайте уникальный индекс (или первичный ключ) для этой таблицы. Тогда вы запросите поиск индексов в обеих таблицах.

Не могу сказать, что производительность была бы лучше, вам пришлось бы тестировать ее на своих данных.

0 голосов
/ 06 сентября 2018

Я также предлагаю объединение, но мое могло бы отличаться от Билла К следующим образом:

SELECT DISTINCT r.user_id 
FROM records AS r 
LEFT JOIN (SELECT DISTINCT user_id FROM records WHERE record_type = 3) AS rt3users
   ON r.user_id = rt3users.user_id
WHERE rt3users.user_id IS NULL
;

Однако есть альтернатива, от которой я не ожидал бы лучшей производительности, но стоит проверить, поскольку производительность может варьироваться в зависимости от размера и содержания данных ...

SELECT DISTINCT r.user_id 
FROM records AS r 
WHERE r.user_id NOT IN (
   SELECT DISTINCT user_id 
   FROM records 
   WHERE record_type = 3
)
;

Обратите внимание, этот больше похож на ваш оригинал, но устраняет коррелированную природу исходного подзапроса.

0 голосов
/ 06 сентября 2018

Я бы сделал это так:

SELECT u.user_id
FROM (SELECT DISTINCT user_id FROM records) AS u
LEFT OUTER JOIN records as r
  ON u.user_id = r.user_id AND r.record_type = 3
WHERE r.user_id IS NULL

Это позволяет избежать коррелированного подзапроса в вашем решении НЕ СУЩЕСТВУЕТ.

Кроме того, у вас должна быть другая таблица, в которой просто перечислены пользователи, поэтому вам не нужно выполнять подзапрос:

SELECT u.user_id
FROM users AS u
LEFT OUTER JOIN records as r
  ON u.user_id = r.user_id AND r.record_type = 3
WHERE r.user_id IS NULL

В любом случае, это поможет оптимизировать JOIN для добавления составного индекса на пару столбцов:

ALTER TABLE records ADD KEY (user_id, record_type)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...