Запросить таблицу, исключая значения, указанные в других таблицах - PullRequest
1 голос
/ 15 февраля 2020

У меня есть база данных, заполненная транзакциями с различных банковских счетов. Каждая транзакция поставляется с user_id, bank_id, account_id и transaction_id. Я хотел бы исключить транзакции при запросе, если пользователь предпочитает игнорировать банк, счет или отдельную транзакцию.

Другими словами, если пользователь:

  • игнорирует банк, все транзакции с этим bank_id пропускаются,
  • игнорирует учетную запись, все транзакции с этим account_id пропускаются,
  • игнорирует отдельную транзакцию, транзакция с этим transaction_id пропущен.

Моя текущая база данных выглядит следующим образом:

-- Simplified for brevity.
CREATE TABLE IF NOT EXISTS transactions
(
    user_id        TEXT NOT NULL,
    transaction_id TEXT NOT NULL,
    account_id     TEXT NOT NULL,
    bank_id        TEXT NOT NULL,
    PRIMARY KEY (user_id, transaction_id)
);

-- Exclusion tables for banks and accounts are similar.
CREATE TABLE IF NOT EXISTS excluded_transactions
(
    id             INTEGER PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
    user_id        TEXT NOT NULL,
    transaction_id TEXT NOT NULL
);

CREATE INDEX IF NOT EXISTS exc_trn_idx ON excluded_transactions (user_id, transaction_id);

Всякий раз, когда пользователь abc исключает банк, счет или транзакцию, он добавляется к соответствующему исключению. Таблица. Затем запрос выглядит следующим образом:

WITH b AS (
  SELECT bank_id FROM excluded_banks WHERE user_id = 'abc'
), a AS (
  SELECT account_id FROM excluded_accounts WHERE user_id = 'abc'
), t AS (
  SELECT transaction_id FROM excluded_transactions WHERE user_id = 'abc'
)
SELECT * FROM transactions 
WHERE user_id = 'abc'
AND bank_id NOT IN (SELECT * FROM b) 
AND account_id NOT IN (SELECT * FROM a)
AND transaction_id NOT IN (SELECT * FROM t)

Это дает производительность OK на тестовом наборе ~ 1M транзакций (время планирования ~ 100 мс, время выполнения ~ 1 с, в среднем). Тем не менее, я беспокоюсь, что он будет значительно ухудшаться по мере роста базы данных.

Мой вопрос : как я могу улучшить таблицы / запросы для эффективного извлечения транзакций с вышеупомянутыми ограничениями? Более медленные записи допустимы, если они ускоряют чтение. Кроме того, если общий подход, который я выбрал, является неоптимальным, пожалуйста, дайте мне знать и / или предложите улучшенный.

1 Ответ

3 голосов
/ 15 февраля 2020

Я бы предложил написать это как:

SELECT t.*
FROM transactions t
WHERE t.user_id = 'abc' AND
      NOT EXISTS (SELECT 1
                  FROM excluded_banks eb
                  WHERE eb.bank_id = t.bank_id AND
                        eb.user_id = t.user_id
                 ) AND
      NOT EXISTS (SELECT 1
                  FROM excluded_accounts ea
                  WHERE ea.account_id = t.account_id AND
                        ea.user_id = t.user_id
                 ) AND
      NOT EXISTS (SELECT 1
                  FROM excluded_transaction et
                  WHERE et.transaction_id = t.transaction_id AND
                        et.user_id = t.user_id
                 );

Тогда убедитесь, что у вас есть следующие индексы:

  • excluded_banks(user_id, bank_id)
  • excluded_accounts(user_id, account_id)
  • excluded_transaction(user_id, transaction_id)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...