Производительность UPSERT (ON CONFLICT) по сравнению с двумя запросами UPDATE или INSERT

Мой код должен работать на разных версиях SQLite. Я использую расширение PHP SQLite3. На разных серверах в моей пользовательской базе установлены разные версии SQLite, самой ранней из которых является 3.7.

Мой код должен обновиться (обновить строку, вставить, если ее нет). Все завернуто в транзакции, а столбец name TEXT имеет уникальный индекс. Я не могу сделать name первичный ключ, потому что БЕЗ ROWID стал доступен только с версии 3.8.2, а мне нужна поддержка более ранних версий.

Я начал с подготовленного оператора upsert:

INSERT INTO tbl (name, value) VALUES (:n, :v)
    ON CONFLICT(name) DO UPDATE SET value=excluded.value;

Это не работает до версии 3.24. Поэтому я переключился на два оператора с вызовом .changes() между ними. Псевдокод:

UPDATE tbl SET VALUE = :v WHERE name = :n;
if (0 === conn.changes()) {
  INSERT INTO tbl (name, value) VALUES (:n, :v);
}

Является ли синтаксис «UPSERT… ON CONFLICT…» значительно быстрее? Стоит ли писать условный код, чтобы использовать его, когда позволяет версия SQLite? Или код с вызовом .changes() между операторами работает адекватно даже в более новых версиях? Я забочусь о хорошей производительности любой версии SQLite, доступной моему пользователю.

Этот вопрос, вероятно, лучше подходит для сайта DBA, а не для SO.

PChemGuy 21.11.2022 15:54
Шлюз в PHP
Шлюз в PHP
API-шлюз (AG) - это сервер, который действует как единая точка входа для набора микросервисов.
Socialite Login With Google Account In Laravel 9
Socialite Login With Google Account In Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com.
Обновление драйверов Microsoft ODBC (с 17 до 18) для PHP
Обновление драйверов Microsoft ODBC (с 17 до 18) для PHP
Все знают, что PHP v7.4 потерял поддержку, и наши недавние старые приложения должны обновиться до PHP v8.x. ...
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как создать PHP Image с нуля
Как создать PHP Image с нуля
Сегодня мы создадим PHP Image from Scratch для того, чтобы легко развернуть базовые PHP-приложения. Пожалуйста, имейте в виду, что это разработка для...
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
0
1
79
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

name должен быть первичным ключом или иметь уникальный индекс.

UPSERT выполнит поиск по индексу, чтобы определить, присутствует ли уже :n, а затем прочитает страницу из таблицы и запишет ту же страницу обратно (либо для обновления значения, либо для добавления новой строки). Если добавляется новая строка, индекс также необходимо обновить.

Комбинация UPDATE + INSERT также выполнит поиск по индексу, чтобы определить, присутствует ли уже :n. Если это так, он прочитает страницу из таблицы и запишет ту же страницу обратно, чтобы обновить значение, как в случае с UPSERT. Если это не так, то INSERT снова выполнит тот же поиск по индексу (который должен быть быстрым, поскольку нужные страницы, вероятно, будут в кеше), а затем выполнит вставку и обновление индекса, как и в случае с UPSERT.

Итак, единственное отличие — поиск по индексу (одна из самых быстрых операций) на страницах, которые уже должны быть в кеше, и только в том случае, если строка должна быть вставлена.

Это не должно быть существенной разницей, если только ваша таблица не содержит миллиарды записей.

Другие вопросы по теме