Как выполнить пакетный запрос к таблице только для добавления в mysql? - PullRequest
0 голосов
/ 05 марта 2020

Предположим, у меня есть таблица только для добавления:

CREATE TABLE IF NOT EXISTS `states` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`start_date` date DEFAULT NULL,
`end_date` date DEFAULT NULL,
`person_id` int(10) unsigned default NULL,
PRIMARY KEY (`id`)

);

Существует индекс на name и другой на person_id (person_id - это fkey ссылка на другую таблицу).

Для каждого имени мы сохраняем сопоставление с person_id для данного диапазона дат. Отображение от name -> person_id - это множество к одному (это надуманный пример, но он воспринимается как хранение того, как человек может изменить свое имя). Мы никогда не хотим удалять историю, поэтому при изменении отображения мы вставляем новую запись. Последняя запись для данного имени является источником правды. В итоге мы хотим задать два разных типа вопросов в наборе данных, для которых у меня есть несколько общих вопросов.

  1. Каково текущее отображение для данного имени / списка имен?

Если есть только одно имя, самый простой запрос:

select * from states where name = 'name' ORDER BY `id` DESC LIMIT 1;

Если существует более одного имени, лучший способ, который я могу выяснить, это сделать:

select * from states as a 
    left join states as b on a.name = b.name and a.id < b.id
where isnull(b.id);

Действительно ли это лучший способ пакетного запроса? Для пакета 1, насколько хуже будет второй запрос, чем первый? Используя объяснение, я могу сказать, что в итоге мы выполнили два поиска по индексу вместо 1. Учитывая, что мы очень заботимся о производительности этого отдельного поиска, моя интуиция заключается в том, чтобы выполнять разные запросы в зависимости от количества имен, для которых мы запрашиваем. Я бы предпочел, если бы был способ отложить оптимизатор mysql. Есть ли способ написать этот запрос, чтобы mysql выяснил, что мне делать?

Какие текущие сопоставления отображаются в person_id / список person_id с?

Я бы запросил это:

select * from states as a 
    left join states as b on a.name = b.name and a.id < b.id
where isnull(b.id) and person_id in person_id_list

Я немного обеспокоен производительностью небольших списков, потому что мое понимание того, как работает mysql, ограничено. Используя объяснение, я знаю, что mysql фильтрует по person_id по индексу перед фильтрованием по isnull (b.id). Но делает ли это до объединения или после объединения? Можем ли мы в конечном итоге тратить много времени на объединение этих двух столов? Как я мог понять это вообще?

1 Ответ

0 голосов
/ 09 марта 2020

Код в (1) "groupwise-max", но сделан очень неэффективным способом. (Следуйте метке, которую я добавил для дальнейшего обсуждения.)

Могу ли я предложить вам две таблицы; тот, который только для добавления, как у вас есть. Давайте назовем эту таблицу History. Затем есть другая таблица с именем Current. Когда вы добавляете новую запись, INSERT в History, но заменяете ее на Current.

. Если вы все-таки выберете этот подход, подумайте, какие различия вы можете иметь в этих двух таблицах. PRIMARY KEY определенно будет другим; другие индексы могут отличаться, и даже некоторые столбцы могут отличаться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...