mysql

hYPER-ok
На сайте с 09.10.2010
Offline
71
969

Ребят, такая фигня:

есть таблица `teams` с полями id, name

пусть там будет 1 команда {44, superTeam}

есть таблица `matches` с полями id, enemy1, enemy2 (enemy1 и enemy2 - содержат ID команд)

пусть там будет 1 матч {1, 15, 44}

в голову приходят только 2 решения:

1. дублирование матчей (т.е. для каждого матча 2 записи, где ID команд в полях enemy1 и enemy2 местами меняются)

2. делать селект через OR (т.е. WHERE enemy1 = '$teamid' OR enemy2 = '$teamid')

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

Может есть по-лучше решение, помогите :)

I
На сайте с 06.08.2012
Offline
1
#1

Как насчет использования одного поля и функции serialize?

У нас две команды, как я понял. Создаем массив с их id, одномерный или двумерный - реализация от этого не меняется. Пусть это будет

$arr = array(15,44);

Перед занесением в базу данных запаковываем массив в строку.

$arr_packed = serialize($arr);

Массив принимает вид a:2:{i:0;i:15;i:1;i:44;} и именно эта строка заносится в БД.

Что касается поиска - в зависимости от количества записей. Для небольших таблиц вполне можно использовать LIKE.

Критерием поиска для 44й команды будет i:44;

Пример: SELECT * FROM `table1` WHERE `column1` LIKE '%i:44;%'

Для небольших таблиц - понятие относительное, но лично я знаю индивидуума, который использует RLIKE (съедающий еще больше ресурсов, используется для поиска по regexp) в случае с таблицей, имеющей более 150к записей :)

hYPER-ok
На сайте с 09.10.2010
Offline
71
#2

Вы уверены, что LIKE будет быстрее работать чем OR?

I
На сайте с 06.08.2012
Offline
1
#3
hYPER-ok:
Вы уверены, что LIKE будет быстрее работать чем OR?

Вы и сами знаете ответ наверняка.

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

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

hYPER-ok
На сайте с 09.10.2010
Offline
71
#4

Было бы не плохо увидеть результаты тестов.

I
На сайте с 06.08.2012
Offline
1
#5
hYPER-ok:
Было бы не плохо увидеть результаты тестов.

Хмм.. Результатами я озадачен:)

Заполнял таблицы на 10000 записей рандомными значениями в диапазоне от 10 до 99.

Ваша таблица состоит из трех полей - id, team1, team2 - все типа INT.

Моя - из двух полей, (INT) id и (VARCHAR[32]) teams.

Запросы в цикле for, 100 итераций.

$num = rand(10,99);
$query1 = mysql_query("SELECT * FROM `table1` WHERE `team1`='".$num."' OR `team2`='".$num."'");
$query2 = mysql_query("SELECT * FROM `table2` WHERE `teams` LIKE '%i:".$num.";%'");

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

А удивило меня вот что - отличий нет (я ожидал выигрыш вашего варианта в пределах 20-30%). Вероятно, надо было тестировать на 100к+ записей :)

Вопросы? Предложения?

png 1344703920466.png
dkameleon
На сайте с 09.12.2005
Offline
386
#6
iNfame:
У нас две команды, как я понял. Создаем массив с их id, одномерный или двумерный - реализация от этого не меняется. Пусть это будет

а если это будет:

$arr = array(15,40,'i:44');

?

---------- Добавлено 11.08.2012 в 20:39 ----------

hYPER-ok:
2. делать селект через OR (т.е. WHERE enemy1 = '$teamid' OR enemy2 = '$teamid')

это вполне нормальное решение.

ещё может быть такая таблица:

match,team

1,15

1,44

c уникальным ключом по match+team

но автоинкремент матчей вы уже не сделаете в этой же таблице

с друзьями - тоже через ИЛИ нормально.

ещё может быть логика при которой вася друг пети, а петя не друг васи. во ВК так есть. одностороння дружба = подписчик.

Дизайн интерьера (http://balabukha.com/)
I
На сайте с 06.08.2012
Offline
1
#7
dkameleon:
а если это будет:
$arr = array(15,40,'i:44');

?

А при каких условиях, простите, это возможно, если мы в массив вносим два параметра типа INTEGER, которые являются айдишниками (праймари-ключи) из таблицы "команды"? :)

Что касается варианта с OR - ничего против него не имею, здесь его использование оправдано. Автора просил альтернативу - я предложил.

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

Другое дело - надо ли оно? Видимо, нет.

hYPER-ok
На сайте с 09.10.2010
Offline
71
#8

Насчет дружбы - про подписчиков не догадался.

А вот насчет матчей - если подумать как для турниров делать селект, то скорее к предложенному варианту Dkameleon.

dkameleon
На сайте с 09.12.2005
Offline
386
#9
iNfame:
А при каких условиях, простите, это возможно, если мы в массив вносим два параметра типа INTEGER, которые являются айдишниками (праймари-ключи) из таблицы "команды"?

а на каких условиях, простите, неоходимо генерировать говнокод, усложняющий последующую работу? :)

ну захотели например изменить числовые индексы на строчные - по номерам команды идентифицировать стало сложно и решили присвоить им строчные коды.

iNfame:
Исключительно вопрос привычки. Как оказалось, мой вариант работает ничуть не медленнее, однако его проще расширять

серьёзно? :)) а как, интересно, вы джойны будете делать?

или будете рубить тремя простыми селектами?

например нужно вывести на экране названия участников первого матча. дерзайте.

а чтоб ещё интереснее - выведите турнирную таблицу и посчитайте запросы.

iNfame:
(например, если бы в каждой игре участвовало 16 команд, разумнее использовать запаковку массива, чем создавать таблицу с 16+ полями).

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

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

I
На сайте с 06.08.2012
Offline
1
#10
dkameleon:
...

Окай. Спасибо, май бэд, признаю.

Даже оправдываться не буду:) Разнесли в щепки:)

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий