Вставка большого количества записей в начало таблицы
Господа, подскажите пожалуйста решение, сам увы додуматься не могу. Есть сервис, в нем есть три таблицы, одна основная, две дочерние. На основной выставлены внешние ключи на дочерние. Формат таблицы основной: id, id_table1, id_table2, data (datetime), text. Таблица с логами. Кроме того, еще эта таблица зацеплена внешним ключем с еще одной, куда заносятся только необходимые записи. Так вот задача, раньше логи велись в файлах, их скопилось огромное количество. Хочется из занести все в эту большую табличку, но проблема в том, каким образом сделать смещение автоинкремента. Единственный вариант какой я вижу это по шагам:
1) узнать сколько записей будем вставлять новых
2) остановить запись логов на некоторое время
3) посчитать сколько записей в текущей таблицы и высчитать необходимое смещение
4) увеличить автоинкремент на необходимое смещение
5) запустить запись логов обратно, запись пойдет с нужным смещением
6) пробежаться с хвоста старого блока данных передвигая каждую запись на смещение
7) освободить в начале таблицы нужное место под новые данные
8) вставить новые данные в начало таблицы с принудительным указанием ИД записи
Быть может есть более оригинальное решение? Ибо смещать придется блок из примерно 700к записей в одной и 200к записей в другой таблице. буду крайне благодарен за ответы.
А зачем вам смещение? Если у вас лог то там наверняка должна быть дата со временем, а при выборе или создании отчета вы всегда можете отсортировать по времени.
я бы сделал так:
1. создал новые таблицы.
2. зафигачил туда все из файлов.
3. отключил логи и констраинты
4. insert into новые_таблицы select (все поля кроме PK) from старые таблицы.
5. переименовал таблички, включил констраинты логи.
Ну да, вариант примерно как мой. Единственное но, что логи пишутся в шесть потоков с интервалом в 10 секунд. Можно сделать блокировку через мемкеш скажем, пока один из процессов не произведет все действия. Только боюсь я не уложиться в 10ть секунд с подсчетом количества записей, сменой инкримента и тд
Вы же логи не по id сортируете? Если всеже по id, не знаю на солько правильный вариант:
Добавить новое поле под инкремент
Добавить записи
Старым выставить старым записям новые id
удалить старое поле
Конечно не по ИД) Просто внутри меня сидит некий гибрид педанта с перфекционистом, который говорит что по логике вещей, более старые записи должны располагаться в начале таблицы, а не в конце.
У БД нет начала и нет конца, есть просто записи. Когда вы их выводите — идет сортировка, если явно ее указать — по id. В целом бд вообще все равно как вы в нее записываете данные и как достаете. Так что просто добавьте записи и проставьте им старое число. Id можно вообще убрать, и поставить индекс только на дату. id вам не нужно
Раньше у MySQL была проблемка с миллисекундами, которая не позволяла создавать записи в таблицу с «индексом только на дату» чаще, чем одна в секунду. Не знаю как сейчас…
уточню еще более. есть таблица 1, куда валятся вообще все записи логов. Логи складывают шесть программ, назовем их так каждые десять секунд. формат лога это джейсон массив. Есть таблица 2, куда при определенном стечении обстоятельств из таблицы 1, из массива вытаскиваются несколько элементов, и в таблице 2 есть поле, log_id, которое внешним ключом сцеплено с таблицей 1. сделано это для того, что-бы в случае необходимости, можно было быстро посмотреть полную информацию о том или ином событии. именно поэтому первичный ключ в виде айдишника в таблице логов нужен.
Пишите секунды в одно поле, милисекунды — другое. Когда будете выбирать — выбирайте по двум полям сразу — нет проблем.
У вас же логи скорее всего microtime(true) берут за время? Ну тогда просто float колонку и вперед. На выводе и преобразуете
Индекс же нужен для того, чтобы выборка производилась быстрее, а вам совершенно плевать на индекс записи при выборке, вам важна дата. Так что id вам просто не нужен, только если для связи.
Увы но нет, обыкновенный таймстамп, который в базе ложится в поле формата datetime. не хотелось дублировать данные и там и там. Я вашу мысль понял, подумаю как можно применить к нашей ситуации
Решение интересное, в данный момент думаем все таки насчет разделения бд, ибо она растет как на дрожжах. наткнулся еще на интересный gist по этому поводу. Единственное, пока не могу понять, каким образом можно скажем определить на какой ноде лежит нужная запись по uuid
Сейчас база небольшая, самые жирные таблицы имеют около 1кк записей, в день добавляется около 50к записей. Нужные сразу вытягиваются в другую табличку, и уже там ставятся внешние включи на текущую таблицу.