Реклама на сайте Advertise with us

Знатоки MySQL, подскажите, плз.

Расширенный поиск по форуму
 
Новая тема Новая тема   
Автор
Поиск в теме:

>100 сайтов вебкам. ссылки.

С нами с 31.03.08
Сообщения: 2372
Рейтинг: 3463


Передовик Master-X (16.12.2016) Передовик Master-X (01.01.2017)
Ссылка на сообщениеДобавлено: 24/12/10 в 02:16       Ответить с цитатойцитата 

предположим, есть таблица в MySQL, в которой имеются поля id, key1, key2.
поле id - автоинкрементное.
поля key1 и key2 в комбинации должны быть Unique.

т.о., id увеличивается на 1, независимо от того, была ли осуществлена запись в базу, или из-за наличия дубликата запись не состоялась. это создает в нумерации "дыры", что крайне неудобно для дальнейшей работы с базой.

порывшись в инете, я нашел несколько вариантов решений данной проблемы.
1. можно перед каждой новой записью давать команду ALTER TABLE 'My_Table' AUTO_INCREMENT=1 (но это лишняя нагрузка на сервер)
2. можно сделать отдельное поле, куда вписывать порядковый номер одновременно с остальными данными. (но это нужно каждый раз опрашивать базу, какой последний номер использован, а при многопоточности это вообще плохо реализуемо.)
3. можно время от времени удалять поле id и добавлять его заново. при этом база сама пронумерует все записи строго по порядку. (но при этом придется каждый раз вручную останавливать все модули, работающие с базой, а потом заново их запускать.)

ни одно из этих решений мне не нравится.
с базой будут работать несколько модулей, и каждый из них - в несколько потоков. база будет большая - счет записей будет идти на миллионы.

подскажите, плз, кто знает, как в такой ситуации лучше поступить? какое решение использовать, чтобы минимизировать нагрузку на сервер/базу?

Продвижение сайтов в GOOGLE.COM и GOOGLE.DE. ICQ в профиле.

0
 



С нами с 07.10.01
Сообщения: 4835
Рейтинг: 3672


Передовик Master-X (16.06.2008)
Ссылка на сообщениеДобавлено: 24/12/10 в 03:38       Ответить с цитатойцитата 

А не проще проверять уникальность key1/key2 до записи в базу?

Лучшие в Рунете: товарная партнёрка - от 4 рублей за клик.
CPA агрегатор - тысячи отличных офферов!

6
 



С нами с 28.07.07
Сообщения: 425
Рейтинг: 375

Ссылка на сообщениеДобавлено: 24/12/10 в 08:46       Ответить с цитатойцитата 

а как у вас проверяется уникальность полей key1, key2 на каком этапе?
может их проверять раньше или создавать транзикацию перед записью, записывать и если поля не прошли проверку отменять. поле не увеличиться и сохраниться многопоточность приложения.

VPS от 10$.USA/Germany

6
 



С нами с 31.05.10
Сообщения: 1991
Рейтинг: 487

Ссылка на сообщениеДобавлено: 24/12/10 в 14:48       Ответить с цитатойцитата 

а почему нельзя сделать уникальное поле hash и писать туда md5(key1.key2)?
при добавлении записи в бд в такой схеме нет необходимости доп. селектов.

6
 



С нами с 01.04.07
Сообщения: 4378
Рейтинг: 2970

Ссылка на сообщениеДобавлено: 24/12/10 в 15:39       Ответить с цитатойцитата 

Я может чего-то не понял, но чем индексы не подходят?
Код:
UNIQUE INDEX 'back_in_the_u_key' ('key1', 'key2')

6
 

>100 сайтов вебкам. ссылки.

С нами с 31.03.08
Сообщения: 2372
Рейтинг: 3463


Передовик Master-X (16.12.2016) Передовик Master-X (01.01.2017)
Ссылка на сообщениеДобавлено: 24/12/10 в 15:58       Ответить с цитатойцитата 

kodek дык, чтобы уникальность проверить, нужно будет запрос в базу делать. имхо, это будет грузить сервер намного больше, чем просто каждый раз "обнулять" автоинкремент.

artursn уникальность никак не проверяется. просто делается попытка записать очередную пару кеев в базу. если попытка удалась, значит пара уникальна. если не удалась, значит она уже существует. но при этом id (автоинкремент) все-равно увеличивается на 1.

LeadFarmer, gimcnuk сорри, но будучи почти полным нубом в вопросах MySQL, я не понял, о чем речь. разжуйте, если можно, и по возможности примитивным языком. icon_redface.gif

а пока всем спасибо и плюшки. icon_biggrin.gif

Продвижение сайтов в GOOGLE.COM и GOOGLE.DE. ICQ в профиле.

0
 



С нами с 01.04.07
Сообщения: 4378
Рейтинг: 2970

Ссылка на сообщениеДобавлено: 24/12/10 в 16:09       Ответить с цитатойцитата 

Цитата:
В MySQL ключ UNIQUE может иметь только различающиеся значения. При попытке добавить новую строку с ключом, совпадающим с существующей строкой, возникает ошибка выполнения команды.


Добавляешь к своей базе
Код:
ALTER TABLE your_table ADD UNIQUE INDEX 'un_in' ('key1', 'key2')


либо при создании
Код:
CREATE TABLE your_table (..., UNIQUE INDEX 'un_in' ('key1', 'key2'))

0
 

>100 сайтов вебкам. ссылки.

С нами с 31.03.08
Сообщения: 2372
Рейтинг: 3463


Передовик Master-X (16.12.2016) Передовик Master-X (01.01.2017)
Ссылка на сообщениеДобавлено: 24/12/10 в 19:06       Ответить с цитатойцитата 

gimcnuk, дык, это я сделал изначально.
проблема не в том, как избежать дубликатов, а в том, как с минимальной нагрузкой для сервера сделать так, чтобы автонумерация в поле id (автоинкремент) не имела "дыр".
пример:
база пуста.
заносим в базу "А1", "B1". id автоматически получает значение 1.
заносим в базу "А2", "B1". id автоматически получает значение 2.
заносим в базу "А1", "B1". запись не производится, т.к. это дубликат. id автоматически получает значение 3.
заносим в базу "А2", "B2". id автоматически получает значение 4.

если вывести все содержимое таблицы, имеем:
id key1 key2
1 A1 B1
2 A2 B1
4 A2 B2

а хотелось бы, чтобы значения id шли по порядку при любом раскладе.

Продвижение сайтов в GOOGLE.COM и GOOGLE.DE. ICQ в профиле.

0
 



С нами с 24.10.04
Сообщения: 18881
Рейтинг: 9010


Передовик Master-X (16.03.2006) Передовик Master-X (01.04.2006) Передовик Master-X (16.04.2006) Передовик Master-X (01.05.2006) Передовик Master-X (01.11.2006) Ветеран трепа Master-X ()
Ссылка на сообщениеДобавлено: 24/12/10 в 19:42       Ответить с цитатойцитата 

sergio21 писал:
gimcnuk, дык, это я сделал изначально.
проблема не в том, как избежать дубликатов, а в том, как с минимальной нагрузкой для сервера сделать так, чтобы автонумерация в поле id (автоинкремент) не имела "дыр".
пример:
база пуста.
заносим в базу "А1", "B1". id автоматически получает значение 1.
заносим в базу "А2", "B1". id автоматически получает значение 2.
заносим в базу "А1", "B1". запись не производится, т.к. это дубликат. id автоматически получает значение 3.
заносим в базу "А2", "B2". id автоматически получает значение 4.
если вывести все содержимое таблицы, имеем:
id key1 key2
1 A1 B1
2 A2 B1
4 A2 B2
а хотелось бы, чтобы значения id шли по порядку при любом раскладе.


странно, у меня примерно такая же конструкция и ид идут подряд, хотя 10% дубликатов проскакивают, а заносишь как INSERT IGNORE?

6
 

>100 сайтов вебкам. ссылки.

С нами с 31.03.08
Сообщения: 2372
Рейтинг: 3463


Передовик Master-X (16.12.2016) Передовик Master-X (01.01.2017)
Ссылка на сообщениеДобавлено: 24/12/10 в 20:30       Ответить с цитатойцитата 

ibiz: нет, делаю простой INSERT.
IGNORE просто "подавляет" сообщения об ошибках, превращает их в предупреждения.
все остальное происходит так-же, как описано выше. специально попробовал добавить в команду IGNORE. результат прежний.

Оффтопик: ibiz, ты проверь свою базу. сравни количество записей и самый большой ID, который там есть. думаю, будет разница.

Продвижение сайтов в GOOGLE.COM и GOOGLE.DE. ICQ в профиле.

0
 



С нами с 24.10.04
Сообщения: 18881
Рейтинг: 9010


Передовик Master-X (16.03.2006) Передовик Master-X (01.04.2006) Передовик Master-X (16.04.2006) Передовик Master-X (01.05.2006) Передовик Master-X (01.11.2006) Ветеран трепа Master-X ()
Ссылка на сообщениеДобавлено: 24/12/10 в 21:40       Ответить с цитатойцитата 

sergio21 писал:

пример:
база пуста.
заносим в базу "А1", "B1". id автоматически получает значение 1.
заносим в базу "А2", "B1". id автоматически получает значение 2.
заносим в базу "А1", "B1". запись не производится, т.к. это дубликат. id автоматически получает значение 3.
заносим в базу "А2", "B2". id автоматически получает значение 4.
если вывести все содержимое таблицы, имеем:
id key1 key2
1 A1 B1
2 A2 B1
4 A2 B2
а хотелось бы, чтобы значения id шли по порядку при любом раскладе.



специально создал отдельную таблицу и попробовал

Код:
CREATE TABLE `ztest` (
  `Id` int(11) NOT NULL auto_increment,
  `key1` varchar(255) NOT NULL default '0',
  `key2` varchar(255) NOT NULL default '0',
  PRIMARY KEY  (`Id`),
  UNIQUE KEY `key1_key2` (`key1`,`key2`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251;


Код:
sql_query("INSERT IGNORE INTO ztest(key1,key2) VALUES ('A1','B1');");
sql_query("INSERT IGNORE INTO ztest(key1,key2) VALUES ('A2','B1');");
sql_query("INSERT IGNORE INTO ztest(key1,key2) VALUES ('A1','B1');");
sql_query("INSERT IGNORE INTO ztest(key1,key2) VALUES ('A2','B2');");


результат
Код:
1   A1   B1
2   A2   B1
3   A2   B2

0
 

Добрых Дел Мастер

С нами с 03.05.08
Сообщения: 3143
Рейтинг: 1227

Ссылка на сообщениеДобавлено: 24/12/10 в 21:57       Ответить с цитатойцитата 

sergio21: так в чем сакральный смысл "непопорядковости" первичного ключа? я вот в свое время прочитал весь ман 4.0 по мускулю, и там ни в одном месте нет проблемы этой. Кстати MYISAM вроде не должен так делать. При вставке вставляется "следующий после последнего", а вот в InnoDB эта тема есть, - там все по-другому и где-то на внутреннем уровне этот индекс храниться - и при ошибочной вставке ключ (и удаленные в последствии ключи) считается последним, т.е. есть пропуски. Но это не в коей мере ничему не мешает (вот у меня база в ней 7к строк, а порядковый номер далеко за 15к. и постоянно что-то удаляется, и более того - это поле юзается как внешний ключ для других таблиц, - проблем никаких. ссылочная целостность есть, уникальный "ползунок" для записей есть). Попробуй что ли не юзать автоинкрементное поле, а просто создай id INT NOT NULL и туда при вставке пиши сам числа. и сам отслеживай. Или через LAST_INSERT_ID() попробуй. т.е. получай последний id, прибавляй 1 и вставляй (хотя вряд ли в автоинкремент поле можно самому число вставить, но попробуй).

пришел к победе коммунистического труда

6
 

>100 сайтов вебкам. ссылки.

С нами с 31.03.08
Сообщения: 2372
Рейтинг: 3463


Передовик Master-X (16.12.2016) Передовик Master-X (01.01.2017)
Ссылка на сообщениеДобавлено: 25/12/10 в 00:14       Ответить с цитатойцитата 

ibiz: странно... возможно, это зависит от версии базы. но я нашел в инете достаточно много подобных тем. т.е., такая проблема возникала не только у меня.

FXIX: сакральный смысл в том, что с базой будет работать многопоточная программа. и гораздо проще писать ее, зная, что номера идут по порядку, чем учитывать возможные "дыры" в нумерации. в этом случае придется встраивать дополнительные запросы к базе, которые будут излишне нагружать сервер.
поэтому я изначально пытаюсь найти решение, которое будет наиболее быстрым, простым, и будет создавать минимальную дополнительную нагрузку.

всем спасибо за внимание, всем +6.
буду юзать вариант с командой ALTER TABLE 'My_Table' AUTO_INCREMENT=1 перед каждой новой записью. это устраняет проблему. но не знаю пока, как это будет выглядеть под нагрузкой. попозже попробую непосредственно на сервере.

Продвижение сайтов в GOOGLE.COM и GOOGLE.DE. ICQ в профиле.

0
 



С нами с 24.10.04
Сообщения: 18881
Рейтинг: 9010


Передовик Master-X (16.03.2006) Передовик Master-X (01.04.2006) Передовик Master-X (16.04.2006) Передовик Master-X (01.05.2006) Передовик Master-X (01.11.2006) Ветеран трепа Master-X ()
Ссылка на сообщениеДобавлено: 25/12/10 в 01:05       Ответить с цитатойцитата 

sergio21 писал:
ibiz: странно... возможно, это зависит от версии базы. но я нашел в инете достаточно много подобных тем. т.е., такая проблема возникала не только у меня.


Version: 5.0.91-community

2
 

Криптопохуист

С нами с 05.04.03
Сообщения: 17156
Рейтинг: 6019

Ссылка на сообщениеДобавлено: 25/12/10 в 02:52       Ответить с цитатойцитата 

sergio21 писал:
предположим, есть таблица в MySQL, в которой имеются поля id, key1, key2.
поле id - автоинкрементное.
поля key1 и key2 в комбинации должны быть Unique.

Вопрос из зрительного зала: нахуя тут поле id вообще?

2
 

>100 сайтов вебкам. ссылки.

С нами с 31.03.08
Сообщения: 2372
Рейтинг: 3463


Передовик Master-X (16.12.2016) Передовик Master-X (01.01.2017)
Ссылка на сообщениеДобавлено: 25/12/10 в 14:40       Ответить с цитатойцитата 

Pentarh: чтобы указывать его в цикле программы, которая будет выдергивать одну за другой строки из базы и обрабатывать их.

Продвижение сайтов в GOOGLE.COM и GOOGLE.DE. ICQ в профиле.

0
 



С нами с 28.07.07
Сообщения: 425
Рейтинг: 375

Ссылка на сообщениеДобавлено: 25/12/10 в 15:05       Ответить с цитатойцитата 

а нельзя просто считать все в массив и использовать ид элемента массива?

VPS от 10$.USA/Germany

2
 



С нами с 24.10.04
Сообщения: 18881
Рейтинг: 9010


Передовик Master-X (16.03.2006) Передовик Master-X (01.04.2006) Передовик Master-X (16.04.2006) Передовик Master-X (01.05.2006) Передовик Master-X (01.11.2006) Ветеран трепа Master-X ()
Ссылка на сообщениеДобавлено: 25/12/10 в 15:12       Ответить с цитатойцитата 

artursn писал:
а нельзя просто считать все в массив и использовать ид элемента массива?


если у тебя память резиновая, то можно вообще весь скрипт в памяти всегда хранить smail101.gif

за InnoDB я не скажу, потому что проводил различные тесты на различных машинах и результат скорости всегда был хуже чем при использовании isam

2
 



С нами с 28.07.07
Сообщения: 425
Рейтинг: 375

Ссылка на сообщениеДобавлено: 25/12/10 в 15:23       Ответить с цитатойцитата 

ну в цыкле он же тоже не всю базу считывает.....или я что-то не понял....

VPS от 10$.USA/Germany

1
 



С нами с 24.10.04
Сообщения: 18881
Рейтинг: 9010


Передовик Master-X (16.03.2006) Передовик Master-X (01.04.2006) Передовик Master-X (16.04.2006) Передовик Master-X (01.05.2006) Передовик Master-X (01.11.2006) Ветеран трепа Master-X ()
Ссылка на сообщениеДобавлено: 25/12/10 в 15:36       Ответить с цитатойцитата 

artursn писал:
ну в цыкле он же тоже не всю базу считывает.....или я что-то не понял....


ну вот есть 10к записей, надо выбрать 20 записей с 5600 по 5620, как это сделать?

1
 

>100 сайтов вебкам. ссылки.

С нами с 31.03.08
Сообщения: 2372
Рейтинг: 3463


Передовик Master-X (16.12.2016) Передовик Master-X (01.01.2017)
Ссылка на сообщениеДобавлено: 25/12/10 в 15:37       Ответить с цитатойцитата 

artursn: читаем внимательно первый пост: "...с базой будут работать несколько модулей, и каждый из них - в несколько потоков. база будет большая - счет записей будет идти на миллионы."

отдельные модули и потоки между собой программно не пересекаются. только обращаются к общей базе.
один модуль в несколько потоков пополняет базу.
другие модули считывают из базы отдельные записи (по порядку) и работают с ними.

Продвижение сайтов в GOOGLE.COM и GOOGLE.DE. ICQ в профиле.

0
 



С нами с 28.07.07
Сообщения: 425
Рейтинг: 375

Ссылка на сообщениеДобавлено: 25/12/10 в 15:43       Ответить с цитатойцитата 

sergio21 писал:
Pentarh: чтобы указывать его в цикле программы, которая будет выдергивать одну за другой строки из базы и обрабатывать их.

я понял это примерно так
1 . SELECT * FROM table WHERE key1='' and key2=''
2. Получаем это в двумерный массив массив
3. потом чичтаем foreach ($array as $kay=>$value)
4. и потом делаем с каждой строчкой что нужно
например
foreach ($array as $kay=>$value)
{
echo '<a href=view.php?id='.$value['key1'].'">'.$value['title'].'</a>';
}
Как вариант..

VPS от 10$.USA/Germany

2
 



С нами с 28.07.07
Сообщения: 425
Рейтинг: 375

Ссылка на сообщениеДобавлено: 25/12/10 в 15:45       Ответить с цитатойцитата 

ну тут уже зависит от бизнес-логики базы...

VPS от 10$.USA/Germany

0
 

>100 сайтов вебкам. ссылки.

С нами с 31.03.08
Сообщения: 2372
Рейтинг: 3463


Передовик Master-X (16.12.2016) Передовик Master-X (01.01.2017)
Ссылка на сообщениеДобавлено: 25/12/10 в 15:50       Ответить с цитатойцитата 

artursn писал:
я понял это примерно так
1 . SELECT * FROM table WHERE key1='' and key2=''
...

неправильно понял. если бы я знал содержимое key1 и key2 в записи номер n, зачем мне нужно было бы их еще раз считывать из базы?
будет так:
SELECT key1, key2 FROM table WHERE id = n

n загоняется в цикл.

Продвижение сайтов в GOOGLE.COM и GOOGLE.DE. ICQ в профиле.

0
 

Добрых Дел Мастер

С нами с 03.05.08
Сообщения: 3143
Рейтинг: 1227

Ссылка на сообщениеДобавлено: 25/12/10 в 16:00       Ответить с цитатойцитата 

sergio21: ну а что мешает просто пропускать несуществующие записи? к примеру
Цитата:

mysql> select * from table where id=3;
Empty set (0.00 sec)

ну проходишься ты по порядку по ID-ам в цикле. сразу второй строкой после запроса делаешь проверку на NULL (или array(). в зависимости от либы на которой пишешь) и цикл вверх бросаешь (if(is_null($result)) {continue;}).
Про ALTER TABLE почитай в мане.

Цитата:

In most cases, ALTER TABLE makes a temporary copy of the original table. MySQL incorporates the alteration into the copy, then deletes the original table and renames the new one. While ALTER TABLE is executing, the original table is readable by other sessions. Updates and writes to the table are stalled until the new table is ready, and then are automatically redirected to the new table without any failed updates. The temporary table is created in the database directory of the new table. This can differ from the database directory of the original table for ALTER TABLE operations that rename the table to a different database.

это точно что-то явно несовместимое с миллионами миллионов операций в секунду. здравый смысл включи - изменение структуры таблицы явно не та процедура которой надо сервер дрочить.
ну имхо конечно

пришел к победе коммунистического труда

6
 
Новая тема Новая тема   

Текстовая реклама в форме ответа
Заголовок и до четырех строчек текста
Длина текста до 350 символов
Купить рекламу в этом месте!


Перейти:  



Спонсор раздела Стань спонсором этого раздела!

Реклама на сайте Advertise with us

Опросы

Рецепт новогоднего блюда 2022



Обсудите на форуме обсудить (11)
все опросы »