Comments
Далее можно получать следующий ID из нужной последовательности с помощью функцииВо-первых, функция last_insert_id тут не нужна, можно и сразу с полем работать. В ряде случаев это выйдет даже экономичнее.
last_insert_id():
UPDATE `sequence` SET `some_other_id` = last_insert_id(`some_other_id` + 1);
SELECT last_insert_id();
Во-вторых, метод опасен тем, что блокирует эту единственную запись в таблице. Если другая сессия захочет обновить какой-либо из счетчиков в этой же таблице, то ей придется ждать.
А что вы имеете ввиду под «сразу с полем работать»?
Да, в моем примере блокировка записи будет. Но можно делать не несколько столбцов одной записи, а несколько записей одной таблицы или даже несколько таблиц. Суть была именно в получении гарантированной последовательности без повторений.
Да, в моем примере блокировка записи будет. Но можно делать не несколько столбцов одной записи, а несколько записей одной таблицы или даже несколько таблиц. Суть была именно в получении гарантированной последовательности без повторений.
А что вы имеете ввиду под «сразу с полем работать»?Например, так:
UPDATE `sequence` SET `some_other_id` = `some_other_id`+1;
SELECT `some_other_id` FROM `sequence`;
Или так:UPDATE `sequence` SET `some_other_id` = `some_other_id`+1;
INSERT INTO `some_other_table` (id, textfield) SELECT `some_other_id`, 'какой-то текст' FROM `sequence`;
Второй случай экономичнее, т.к. требует на один запрос меньше.Я правильно понимаю, что вы тут неявно предполагаете, что запросы в ваших примерах должны идти в одной транзакции с блокировкой на запись?
Иначе между UPDATE `sequence` и SELECT FROM `sequence` может произойти что угодно. Аналогично и со вторым вариантом.
Я предлагал решение без явного старта транзакции.
Иначе между UPDATE `sequence` и SELECT FROM `sequence` может произойти что угодно. Аналогично и со вторым вариантом.
Я предлагал решение без явного старта транзакции.
Да, в моем примере блокировка записи будет.Тут я, кстати, не совсем прав. Если включен автокоммит (а это по умолчанию) и если дело не происходит в рамках явно начатой транзакции, то блокировка будет довольно короткая, только на время самого UPDATE-а. Т.е. скорее всего, она будет некритична.
По-моему никто уже в здравом уме не использует Myisam. Это просто ненадежное хранилище данных (без записи в лог). При внезапном выключении электричества в момент записи данных всё бъется, причем не определить, что именно побилось, а что нет.
Задачи бывают разные. И если вас опасность потери данных беспокоит меньше скорости записи то myisam отлично подходит для этой работы.
Запись в таблицу myisam однопоточная. Потому что приходится лочить всю таблицу перед изменением.
Так что innodb гораздо быстрее на запись, если сразу несколько потоков обновляют/вставляют данные.
MyIsam не нужна вообще. Никому.
Так что innodb гораздо быстрее на запись, если сразу несколько потоков обновляют/вставляют данные.
MyIsam не нужна вообще. Никому.
Если у вас insert тормозит, то не пробовали ли вы отключать вызов fsync() на каждую вставку?
Не представляю, как это может быть. Вы что-то не то делаете с innodb
В проекте необходимо высчитывать тысячи различных COUNT(*). На очень многих InnoDB проигрывает в скорости :(
P.S. Заранее хранить их значения в отдельной таблице не представляется возможным
P.S. Заранее хранить их значения в отдельной таблице не представляется возможным
count(*) на MyIsam выигрывает только в случае count по всей таблице, без каких-либо where. Но count по всей таблице делается относительно редко.
Если прям нужен общетабличный count, то можно использовать innodb, но кешировать где-нибудь или еще лучше обновлять по триггеру или по крону время от времени.
Если прям нужен общетабличный count, то можно использовать innodb, но кешировать где-нибудь или еще лучше обновлять по триггеру или по крону время от времени.
может стоит использовать уникальный ID для всей базы данных?
select UUID_SHORT()
select UUID_SHORT()
Вредные советы без понимания мат.части.
На самом деле вставка была, потому что запись сначала удаляется, а потом делается insert с новыми значениями. Чтобы это понимать нужно было прочитать документацию:
и
И если вы указываете primary key с AUTO_INCREMENT зачем при вставке данных в таблицу явно указывать поле id?
Вообще уровень новичка чувствуется по тому, что автор следит за изменением поля AUTO_INCREMENT, созданного для того, чтобы не следить за ним вообще.
Автоинкремент стал 5, хотя вставки не было. А что будет с MyISAM:
На самом деле вставка была, потому что запись сначала удаляется, а потом делается insert с новыми значениями. Чтобы это понимать нужно было прочитать документацию:
REPLACE works exactly like INSERT, except that if an old row in the table has the same value as a new row for a PRIMARY KEY or a UNIQUE index, the old row is deleted before the new row is inserted. See Section 13.2.5, “INSERT Syntax”.
Источник.и
You can use REPLACE instead of INSERT to overwrite old rows. REPLACE is the counterpart to INSERT IGNORE in the treatment of new rows that contain unique key values that duplicate old rows: The new rows are used to replace the old rows rather than being discarded.
Источник.И если вы указываете primary key с AUTO_INCREMENT зачем при вставке данных в таблицу явно указывать поле id?
Вообще уровень новичка чувствуется по тому, что автор следит за изменением поля AUTO_INCREMENT, созданного для того, чтобы не следить за ним вообще.
А я не понимаю как такая статья могла набрать 30 плюсов… Я вот в даже в кошмарном сне не могу представить в каких случаях может понадобится такая структура таблицы «sequence», что нет ни одного обязательного параметра и таблицу можно заполнять нулями…
Для этих целей можно написать триггер.
хотя следить за ним иногда бывает нужно, например, после вставки записи и сразу за этим следующим добавлением данных в связанную таблицу уже с foreign key.
Для этих целей можно написать триггер.
Ок, каким образом вы получите в приложении id, если не «следить» за ним? Например, если у вас, в приложении одна логика для вставки и изменения с одним запросом INSERT… ON DUPLICATE KEY UPDATE?
PS. С REPLACE понятное дело, неудачный оборот «вставки не было», вставка конечно была после удаления. Просто имелось ввиду, что не было вставки новых данных в таблицу.
PS. С REPLACE понятное дело, неудачный оборот «вставки не было», вставка конечно была после удаления. Просто имелось ввиду, что не было вставки новых данных в таблицу.
Оставлять дефолтные настройки на MySQL это очень неправильно. Как минимум нужно выставлять свой fsync и innodb_buffer_pool_size. Так как значения по-умолчанию убивают производительность очень сильно.
Поищите на англ. статьи вроде «MySQL performance tuning» особо порекомендую статьи от Percona.
Поищите на англ. статьи вроде «MySQL performance tuning» особо порекомендую статьи от Percona.
Sign up to leave a comment.
Несколько заметок о MySQL