Добавлять в базу только уникальные строки

Sunday

Cōgitō ergō sum
Регистрация
13 Дек 2009
Сообщения
823
Реакции
342
Требуется создать таблицу и добавлять туда периодически по многу обычных текстовых строк, состоящих из разного кол-ва слов.
Подскажите какие особенности нужно учесть при создании таблицы и как сделать так, чтобы при последующем добавлении строк, дубликаты просто отсеивались, а всё остальное добавлялось?

Спасибо.
 
дубликаты просто отсеивались, а всё остальное добавлялось?Спасибо.
Первый способ
1. Добавить уникальный ключ. Какой тип столбца для хранения строк? Если TEXT - решение не подойдет, для VARCHAR - подойдет, но там также есть ограничение первичного ключа.
2. Делать INSERT IGNORE при добавлении

Второй способ - следить за уникальностью хеша (и надеяться, что не словите коллизию). В принципе Для просмотра ссылки Войди или Зарегистрируйся
 
Если данные "горячие", можно хранить в каком нибудь in memory хранилище (типа redis, memcached)
 
Требуется создать таблицу и добавлять туда периодически по многу обычных текстовых строк.
Если про MySQL (ну или MariaDB) речь, то могу посоветовать следующее:
Индекс, как уже подсказали, должен быть по ключевому полю. Тип таблицы сделайте InnoDB, всю процедуру добавления проведите в одну транзакцию. Тогда обновление индекса произойдет сразу для всей пачки добавленных строк, а не по одной. Скорость вставки будет при этом значительно выше (в разы).
Или можно попробовать сделать тип таблицы MyISAM (работает быстрее, но не поддерживает транзакции, существует незначительный риск потери данных) и перед вставкой записей запросом выключать инлексы, а после вставки включать (в результате индекс будет создан заново).
Советую попробовать на тестовых данных оба эти варианта и выбрать тот, который окажется быстрее.
<-------------- добавлено через 145 сек. -------------->
Если данные "горячие", можно хранить в каком нибудь in memory хранилище (типа redis, memcached)
Не думаю, что "горячие данные" этот случай ТС, но в MySQL есть специально для этого тип таблиц Memory. Работает как обычная таблица, только очень быстро - все данные в памяти, при выключении питания данные из таблицы теряются. Удобно для каких-то промежуточных вычислений.
 
Кто подскажет, а как проверять уникальность в случае если в таблице не одно поле?
К примеру имеем:
Код:
id | name | title
name и title могут повторяться по отдельности, но не должны повторятся одновременно. т.е. если у них общий ID.
 
Кто подскажет, а как проверять уникальность в случае если в таблице не одно поле?
Для этого используется составной индекс:
Код:
CREATE INDEX name_title ON articles(name, title);
 
Не будет работать. И какая у вас БД? В MySQL это ограничение нельзя сделать (если не рассматривать триггеры).
 
думаю это поможет
INSERT ... ON DUPLICATE KEY UPDATE
 
Для примера возьмем такую минималистичную табличку:
Код:
CREATE TABLE `articles` (
  `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(255) NOT NULL,
  `title` VARCHAR(255) NOT NULL,
  PRIMARY KEY (`id`)
) engine=innodb;
Выполним запрос на вставку двух записей:
Код:
INSERT INTO `articles` VALUES
(DEFAULT, 'sample', 'sample'),
(DEFAULT, 'sample 1', 'sample 2')
;
Я выполняю команды из консоли mysql, мне показывается результат. Все вставилось успешно:
Код:
Query OK, 2 rows affected (0.01 sec)
Records: 2  Duplicates: 0  Warnings: 0
Теперь создадим триггер на вставку данных. Он срабатывает при каждой вставке.
Код:
DELIMITER $$
CREATE TRIGGER `before_insert_articles`
BEFORE INSERT ON `articles`
FOR EACH ROW
BEGIN
  IF NEW.name = NEW.title
  THEN
    SIGNAL SQLSTATE '02000' SET MESSAGE_TEXT = 'Error: name = title!';
  END IF;
END$$
DELIMITER ;
Перед строкой "DELIMITER ;" MySQL должен вывести успех:
Код:
Query OK, 0 rows affected (0.00 sec)
Если этого не произошло, то возможные причины:
  • такой триггер уже есть (не наш случай)
  • ошибка синтаксиса (я проверил, не наш случай)
  • текущему пользователю запрещено создавать триггеры. такое может быть на шаред-хостингах. смотрите выхлоп "show grants;"
Продолжим. Попробуем вставить одну "неправильную" запись:
Код:
INSERT INTO `articles` VALUES
(DEFAULT, 'sample', 'sample');
Должно вывестись:
Код:
> ERROR 1643 (02000): Error: name = title!
Вставка не произошла. Попробуем случай посложнее, где вторая строка проходит условие:
Код:
INSERT INTO `articles` VALUES
(DEFAULT, 'sample', 'sample'),
(DEFAULT, 'sample 3', 'sample 4')
;
Получим ту же самую ошибку:
Код:
> ERROR 1643 (02000): Error: name = title!
Это произошло потому что триггер работает на уровне запросов.
У нас в таблице уже есть две записи:
Код:
mysql> select * from articles;
+----+----------+----------+
| id | name     | title    |
+----+----------+----------+
|  1 | sample   | sample   |
|  2 | sample 1 | sample 2 |
+----+----------+----------+
2 rows in set (0.00 sec)
Теперь попробуем сделать "правильную" вторую запись "неправильной":
Код:
mysql> UPDATE `articles` SET name = title;
Query OK, 1 row affected (0.01 sec)
Rows matched: 2  Changed: 1  Warnings: 0
mysql> select * from articles;
+----+----------+----------+
| id | name     | title    |
+----+----------+----------+
|  1 | sample   | sample   |
|  2 | sample 2 | sample 2 |
+----+----------+----------+
2 rows in set (0.00 sec)
Запрос выполнился успешно. Если необходимо задать ограничение на обновление, следует создать еще один аналогичный триггер:
Код:
BEFORE UPDATE ON `articles`
 
Назад
Сверху