Как структурировать модель, которая разбита на базу данных в виде 36 таблиц?

У меня более 1 миллиарда записей доменных имен, которые вместо того, чтобы помещать их в одну таблицу, я решил разбить их на 36 таблиц (одна и та же структура db для каждой таблицы).

Существует таблица, основанная на первом символе имени домена (ex tables: domains_a... domains_z).

Как создать отдельную модель Domain в рельсах, которая автоматически переключается между этими таблицами на основе указанного символа?

Ответ 1

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

Однако есть трюк, который сделает его очень легким для вас. Как справиться с этим на уровне базы данных? Я проверил, и все основные базы данных поддерживают обновляемые представления.

Итак, создайте новое представление, назовите его domains и убедитесь, что он создает объединение всех ваших таблиц домена (от a до z), а затем создает модель:

class Domain
  self.table_name = "your_view_name"
end

Это сделало бы трюк для чтения. Теперь, основываясь на используемой вами базе данных, вы можете решить также проблему записи (с помощью триггеров и аналогичных функциональных возможностей БД), в противном случае вам нужно написать свой собственный код для части записи, которая, вероятно, понадобится запускать необработанные запросы.

В качестве альтернативы вы можете справиться с этим на уровне Ruby, создав все модели (DomainA, DomainB и т.д.) вручную или с помощью генератора, а затем создав общий класс, который действует как интерфейс. Или вы можете создать эти модели с некоторым метапрограммированием и снова иметь общий класс, который работает как интерфейс.

Ответ 2

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

Например, PostgreSQL имеет базовую поддержку . Вы должны указать модель Rails в главной таблице, и разбиение будет прозрачным для слоя Ruby.

Ответ 3

Разделение таблиц - это путь. Не создавайте все эти идентичные структуры таблиц.

Какое разбиение таблиц даст вам

  • У вас будет отдельная таблица, которая логически разбивается на разделы по базе данных.
  • В представлении ваших приложений вы запрашиваете одну таблицу, как и любую другую таблицу базы данных.
  • В перспективе базы данных хранятся данные по разделам, которые определяются типом раздела и логикой раздела. В mysql вы можете обратиться к https://dev.mysql.com/doc/refman/5.7/en/partitioning-types.html
  • Эффективность при правильном определении. Это позволит избежать сканирования 1 миллиарда строк, но вместо этого сканировать связанный раздел при выполнении запросов.

Таблица разделов может быть специфичной для конкретной базы данных.

Простой пример из mysql.

CREATE TABLE employees (
    id INT NOT NULL,
    fname VARCHAR(30),
    lname VARCHAR(30),
    hired DATE NOT NULL DEFAULT '1970-01-01',
    separated DATE NOT NULL DEFAULT '9999-12-31',
    job_code INT NOT NULL,
    store_id INT NOT NULL
)
PARTITION BY RANGE (store_id) (
    PARTITION p0 VALUES LESS THAN (6),
    PARTITION p1 VALUES LESS THAN (11),
    PARTITION p2 VALUES LESS THAN (16),
    PARTITION p3 VALUES LESS THAN MAXVALUE
);

Сотрудник хранится в определенном разделе на p0, p1, p2 или p3 в зависимости от того, в каком хранилище (store_id) находится сотрудник.

Вы по-прежнему получаете доступ к нему через одну таблицу, но данные хранятся логически по разделам в зависимости от store_id.

SELECT * FROM employee WHERE store_id = 10

База данных будет просто смотреть на раздел p1 и не сканировать другой раздел (p0, p2 и p3), потому что просто этот запрос никогда не найдет данные в этом разделе.