Задавайте вопросы, мы ответим
Вы не зашли.
Страниц: 1
Есть таблицы, порядка миллиона записей. Стоит задача периодически удалять записи старше определенного периода (обычно это сутки).
Вот одна из них.
CREATE TABLE `brevno_ext_access` (
`id` bigint(20) unsigned NOT NULL auto_increment,
`siteid` int(10) unsigned NOT NULL,
`sessionid` bigint(20) unsigned NOT NULL,
`ipnum` int(10) unsigned default NULL,
`pageid` int(10) unsigned NOT NULL,
`GET` mediumtext,
`DATE` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `pageid` (`pageid`,`DATE`),
KEY `sessionid` (`sessionid`,`DATE`),
KEY `siteid` (`siteid`,`DATE`),
KEY `ipnum` (`ipnum`),
KEY `DATE` (`DATE`)
) ENGINE=InnoDB AUTO_INCREMENT=6888171 DEFAULT CHARSET=latin1
В условиях отсутствия посторонней нагрузки на таблицу запрос на удаление вида
Неактивен
Лучше всего не удалять много записей одним запросом. Сначала выбрать те, которые надо удалить, а потом удалять по 1000 штук. Тогда система не будет в подвешенном состоянии несколько минус, а удовольствие удаления можно растянуть.
Неактивен
Т.е. узкое место - именно в модификации таблицы, а не в выборке нужных записей?
потом удалять по 1000 штук.
Т.е. удалить 1 раз 100 000 - это хуже, чем 100 раз по 1000, причем сразу один за другим?
Система не сказать, что в очень подвешенном состоянии. Нагрузка не оч. большая, таблица не лочится, т.к. InnoDB. Нужно не только, чтобы система не загружалась, но и чтобы было быстрее. Если время удаления не уменьшится, то смысла мало.
Неактивен
Скорее всего таблица все-таки лочится, если выборка не по первичному ключу. Если это нужно раз в день, то производительность не важна, а вот, чтобы все не висло - нужно.
Неактивен
Вообще предполагалось, что это нужно раз в пять минут (при пятиминутных интервалах удаления требуется где-то десять секунд).
Можно немного поподробнее про 1000 строк: как это разбиение вообще реализовывается? там между этими тысячами интервал ожидания поставить или просто если будут отдельные запросы, то само собой получится?
Лочится вряд ли, т.к. в нее инсерты идут и не написано Locked, написано update.
(кстати; за сутки уже придется не 100 000 строк удалять, а два миллиона).
Неактивен
Я немножко вмешаюсь
1. Можно удалять и балком — к старым записям обращения нету в штатном режиме, поэтому
блокировки не заметны: они ставятся как раз между удаляемыми записями.
2. Удалять логичнее по id (благо, он автоинкрементальный): найти последний удаляемый
по ключу и удалить по primary ключу — чуть-чуть быстрее (блокировки не будут ставиться
на второй ключ).
3. Для логов это, наверное, не самый лучший способ хранения. Традиционно используют
исамовские таблички и «перемещающийся» MERGE/VIEW над ними. Тогда «удаление старых» —
это чрезвычайно быстрая операция.
UPD: Кстати, если заапгрейдиться до 5.1, то при уже работающей схеме чрезвычайно увеличит
скорость добавлений-удалений партишны линейные над датой. По сути — третий пункт, но
несколько завуалированный для пользователя. Даже в случае удаления с WHERE — индекс
будет перестраиваться не на всех записях, а только на нужных разделах. Менее глубокий
индекс => меньше перестраивать => быстрее работает.
Неактивен
Подобные вмешательства только приветствуются
Дело, видимо, не в блокировках - при отсутствии активности по отношению к таблице то же самое получалось.
По id оказалось, к сожалению, так же медленно
Как же можно использовать для логов MyISAM? Не возникает ли проблем от того, что лочится вся таблица при записи?
партишны линейные над датой. По сути — третий пункт, но
несколько завуалированный для пользователя. Даже в случае удаления с WHERE — индекс
будет перестраиваться не на всех записях, а только на нужных разделах. Менее глубокий
индекс => меньше перестраивать => быстрее работает.
к сожалению, настолько высокий полет мысли, что я почти ничего не понял
можно еще раз, почему 5.1 делает менее глубокий индекс, и что такое линейный partition над датой? (я извиняюсь за свою темноту)
Неактивен
Наверное, я просто плохо выразился
Я имел в виду вот такого зверя:
Неактивен
Ух ты, интересно!
Правда, есть ряд проблем:
1. Пока в руководстве написано, что на датой такое можно делать только по дням или годам:
http://dev.mysql.com/doc/refman/5.1/en/ … uning.html
This type of optimization can be applied whenever the partitioning expression consists of an equality or a range which can be reduced to a set of equalities, or when the partitioning expression represents an increasing or decreasing relationship. Pruning can also be applied for tables partitioned on a DATE or DATETIME column when the partitioning expression uses the YEAR() or TO_DAYS() function.
Pruning can be used only on integer columns of tables partitioned by HASH or KEY. For example, this query on table t4 cannot use pruning because dob is a DATE column:
SELECT * FROM t4 WHERE dob >= '2001-04-14' AND dob <= '2005-10-15';
А у нас там таблица всего за сутки...
2. Допустим, такое можно было бы сделать. Тогда встала бы проблема, что разделение слишком быстро устаревает (за сутки данные полностью обновляются). Что делать в случае, когда устаревает разделение? (или просто хочется его переделать)
Это ж он будет заново всю таблицу перестраивать? Если часто так делать, то затраты на это дело могут перекрыть выигрыш...
3. Кстати, каково вменяемое количество частей? Например, таблицу за сутки разбить по минутам - это нормально или уже слишком?
Какие вообще примерно ресурсы требуются для этого? (я имею в виду, при одинаковых данных какие служебные ресурсы задействуются?)
Неактивен
Хм, жуткая особенность
Насколько я помню, под RANGE можно вставить любую функцию, в том числе и UNIXTIME.
PRUNING над целыми числами работает нормально.
Физически каждый раздел = отдельная таблица. Исходи их этих соображений.
Неактивен
Страниц: 1