|
Batler ↓
|
 |
|
15 Август, 2009, 01:29:49
|
НЕ ХУЕТА!
ХУЕТА!
|
|
Карма: 4
Сообщений: 142 Сила слова: 2.82
|
Есть таблица `hotels`. Структура следующая:
id INT AUTO INCREMENT PRIMARY KEY,
name TINYTEXT CHARACTER SET utf8,
region TINYTEXT CHARACTER SET utf8,
type TINYTEXT CHARACTER SET utf8
Мне нужно вставлять в нее строки, причем так, чтобы комбинация name|region|type была уникальная. Как лучше это сделать?
У меня есть идея с использованием UNIQUE KEY comb (name(100), region(50), type(20)) и тогда писать в INSERT'e игнор на повторяющиеся строки.
Только я не уверен, что все это будет работать.
|
|
|
|
|
Записан
|
|
|
|
|
md5 ↓
|
 |
|
15 Август, 2009, 01:31:20 , спустя 1 минуту 31 секунду
|
НЕ ХУЕТА!
ХУЕТА!
|
выезд, апартаменты, массаж, стриптиз, подружки, дорого
Группа: в ухо Карма: не нужна
Сообщений: 10494 Сила слова: 1.19
|
а почему не уверен?
не уверен — не играй!
|
|
|
|
|
Записан
|
8: Undefined variable: str Файл: /home/pyha/pyha.ru/forum/bbcode/Xbb/Tags/Man.php Строка: 18 adw0rd: мудень блять, я уже фиксить стал эту фигню :) md5: вуахахахаха
|
|
|
|
Batler ↓
|
 |
|
15 Август, 2009, 01:33:28 , спустя 2 минуты 8 секунд
|
НЕ ХУЕТА!
ХУЕТА!
|
|
Карма: 4
Сообщений: 142 Сила слова: 2.82
|
Столбец name может содержать более 100 символов, значит в индекс войдет не все
ну и другие подводные камни этого варианта решения
|
|
|
|
|
Записан
|
|
|
|
|
Batler ↓
|
 |
|
15 Август, 2009, 07:08:35 , спустя 5 часов 35 минут 7 секунд
|
НЕ ХУЕТА!
ХУЕТА!
|
|
Карма: 4
Сообщений: 142 Сила слова: 2.82
|
Ок. С индексом получилось. Как теперь его заюзать в селект запросе.
Критерий такой WHERE ROW(name,region,type) IN ( (a,b,c), (d,e,f), (g,h,i) ).
Экслпеин говорит, юзать его не буду, даже если явно прописать USE KEY в SELECT
|
|
|
|
|
Записан
|
|
|
|
|
phpdude ↓
|
 |
|
15 Август, 2009, 07:12:49 , спустя 4 минуты 14 секунд
|
НЕ ХУЕТА!
ХУЕТА!
|
я - ЭМО
Группа: в ухо Карма: 344
Сообщений: 20782 Сила слова: 1.66
|
пошли всю структуру страницы + запрос который хочешь выполнять
|
|
|
|
|
Записан
|
забанен. могу забанить других, пишите в личку BEER. Helping ugly people have sex since 1862.
|
|
|
|
Batler ↓
|
 |
|
15 Август, 2009, 11:36:48 , спустя 4 часа 23 минуты 59 секунд
|
НЕ ХУЕТА!
ХУЕТА!
|
|
Карма: 4
Сообщений: 142 Сила слова: 2.82
|
Страница - но принт. Скрипт будет в консоли крутиться. Вобщем не важно, вот код
$hotelinfo; # список, в котором в формате НАЗВАНИЕ ОТЕЛЯ|РЕГИОН|ТИП хранятся данные. строки могут повторяться, а в бд такого не надо.
$unq = array_unique($hotelinfo); #Рассматриваем неповторяющиеся записи.
/*
*Тут можно пойти 2мя путями. Сделать запрос вида SELECT name, region, type FROM `hotels` WHERE ROW(name, region, type) IN...
* Или задать индекс по столбцам name, region, type и объявить его уникальным. Тогда повторов в таблице не будет.
*/
//Коннект к БД
$db = DB:: getDB();
$select = 'SELECT name, region, type FROM `hotels` WHERE ROW(name, region, type) IN (';
foreach ($unq as $k => & $v) {
$m = explode('|', $v);
$select .= $db-> prepare('($0,$1,$2), ', array($m[0], $m[1], $m[2]));
}
$select = substr($select, 0, sizeof($select) - 2) . ')';
$res = $db-> query($select, null, 'assoc');
//Теперь в $res лежат отели, которые уже есть в базе. Их вставлять не надо...
//Далее идет инсерт в таблицу исключая отели, которые уже есть. Тут не очень интересный код.
//Затем вставленные отели снова выбираются из таблицы, чтобы узнать их ID, а потом этот ID записывается в другую таблицу.
Структура таблицы:
id INT AUTO INCREMENT PRIMARY KEY,
name TINYTEXT CHARACTER SET utf8,
region TINYTEXT CHARACTER SET utf8,
type TINYTEXT CHARACTER SET utf8
Пробовал так:
id INT AUTO INCREMENT PRIMARY KEY,
name VARCHAR(100) CHARACTER SET utf8,
region VARCHAR(100) CHARACTER SET utf8,
type VARCHAR(20) CHARACTER SET utf8,
UNIQUE KEY nrt (name(100), region(100), type(20)))
Тогда селект, который я написал выше вообще больше не нужен, но инсерт начинает тормозить.
|
|
|
|
« Последнее редактирование: 15 Август, 2009, 11:36:18 от Batler »
|
Записан
|
|
|
|
|
phpdude ↓
|
 |
|
15 Август, 2009, 11:38:58 , спустя 2 минуты 10 секунд
|
НЕ ХУЕТА!
ХУЕТА!
|
я - ЭМО
Группа: в ухо Карма: 344
Сообщений: д-о-х-у-я! Сила слова: 1.66
|
но инсерт начинает тормозить.
таблички myisam видимо юзаешь. + сколько записей в таблицах?
|
|
|
|
|
Записан
|
забанен. могу забанить других, пишите в личку BEER. Helping ugly people have sex since 1862.
|
|
|
|
Batler ↓
|
 |
|
15 Август, 2009, 11:49:18 , спустя 10 минут 20 секунд
|
НЕ ХУЕТА!
ХУЕТА!
|
|
Карма: 4
Сообщений: 142 Сила слова: 2.82
|
вообще толстеют очень быстро =)
пока под 4,5к в одной и около 250к в связанной с ней =) Спустя 59 секунд добавил 4,5k - hotels
|
|
|
|
|
Записан
|
|
|
|
|
phpdude ↓
|
 |
|
15 Август, 2009, 11:54:18 , спустя 5 минут
|
НЕ ХУЕТА!
ХУЕТА!
|
я - ЭМО
Группа: в ухо Карма: 344
Сообщений: 20782 Сила слова: 1.66
|
попробуй на иннодб смени таблицы, может отпадут тормоза)
|
|
|
|
|
Записан
|
забанен. могу забанить других, пишите в личку BEER. Helping ugly people have sex since 1862.
|
|
|
|
Batler ↓
|
 |
|
16 Август, 2009, 12:15:08 , спустя 20 минут 50 секунд
|
НЕ ХУЕТА!
ХУЕТА!
|
|
Карма: 4
Сообщений: 142 Сила слова: 2.82
|
Это можно... Еще можно вместо инсерта из файлика загрузку делать...
Индекс очень сильно тормозит на вставке, но самое стремное, он потом в селекте не используется.
Ладно, пробовать буду завтра... посмотрим че выйдет...
|
|
|
|
|
Записан
|
|
|
|
|
ghost ↓
|
 |
|
21 Август, 2009, 01:03:48 , спустя 5 дней 48 минут 40 секунд
|
НЕ ХУЕТА!
ХУЕТА!
|
без вариантов
Группа: в ухо Карма: 29
Сообщений: 876 Сила слова: 3.31
|
можно тригер на инсерт поставить и обойтись без урезанных индексов.
походу непонимаю с какой радости тайп в уникальности учитывается - в регионе могут быть несколько отелей с одинаковым именем но разными типами?
|
|
|
|
|
Записан
|
 Если ты уже два часа споришь с идиотом - скорее всего он делает тоже самое...
|
|
|
|
Batler ↓
|
 |
|
21 Август, 2009, 12:19:06 , спустя 11 часов 15 минут 18 секунд
|
НЕ ХУЕТА!
ХУЕТА!
|
|
Карма: 4
Сообщений: 142 Сила слова: 2.82
|
Угу, звездность и все такое (5+ HV-1 и т.п.). А названия отелей одинаковые, т.к. это политика управления брендом.
Да и как триггер поможет в проверке уникальности? Можно конечно что-то там придумать, но я пока остановился на варианте SELECT -> поиск совпадений->INSERT->SELECT для вставки в другую таблицу и т.п.
|
|
|
|
« Последнее редактирование: 21 Август, 2009, 12:19:06 от Batler »
|
Записан
|
|
|
|
|
AndryG ↓
|
 |
|
21 Август, 2009, 03:58:21 , спустя 3 часа 39 минут 15 секунд
|
НЕ ХУЕТА!
ХУЕТА!
|
|
Группа: Адекваты
Карма: 1
Сообщений: 233 Сила слова: 0.43
|
Не знаю, как mySQL (поддерживает ли он "insert into () select")
Может такой вариант сойдет?
INSERT INTO hotels (name,region,type_)
SELECT :name, :region, :type
FROM rdb$database -- Это таблица с одной строкой. Для mySQL, кажись, можно просто убрать предложение FROM
WHERE NOT EXISTS(SELECT * FROM hotels WHERE name = :name AND region = :region AND type_ = :type)
Если использовать mysqli, то предварительная подготовка запроса в самом начале работы скрипта должна Вам помочь с быстродействием. Спустя 1 минуту 34 секунды добавил type_ c подчеркивание в конце, ибо "type" у меня - служебное слово
|
|
|
|
|
Записан
|
|
|
|
|
Batler ↓
|
 |
|
21 Август, 2009, 04:50:36 , спустя 52 минуты 15 секунд
|
НЕ ХУЕТА!
ХУЕТА!
|
|
Карма: 4
Сообщений: 142 Сила слова: 2.82
|
Prepared statement выполняются медленее в MySQL. Пруфлинк давал в другой ветке (см обсуждение класса для работы с БД).
И я не понял немного логики этого запроса. Вставить в таблицу hotels значения, которые вернет оператор SELECT (а он вернет параметры которые мы проверяем, при условии, что вложенный запрос ничего не вернет). Если я правильно понял запрос, то тут есть проблемы:
1) У нас массив отелей, значит запросов будет множество (пусть даже заранее подготовленных, но тем не менее их будет множество).
2) Подзапрос в запросе. Это тоже не добавит к скорости.
3) Я тоже не уверен, что MySQL держит селект в инсерте. В моей литературе сказано, что не держит, но там версия древняя.
UPD: http://www.mysql.ru/docs/man/INSERT_SELECT.html Есть такая возможность, но там сказано, что нельзя использовать
ту же таблицу, куда производится вставка.
|
|
|
|
|
Записан
|
|
|
|
|
AndryG ↓
|
 |
|
21 Август, 2009, 09:03:05 , спустя 4 часа 12 минут 29 секунд
|
НЕ ХУЕТА!
ХУЕТА!
|
|
Группа: Адекваты
Карма: 1
Сообщений: 233 Сила слова: 0.43
|
Prepared statement
Из той ветки я понял, что подготовленный запрос выполняется медленнее, если он единственный.
А если сравнить выполнение 1000 раз запроса обычного и 1000 раз запроса предварительно подготовленного (1 подготовка и 1000 выполнений)
Если и на многократном исполнении подготовленный запрос проигрывает, то я вообще в шоке от этой СУБД :)
(Но это уже вариации ПО - не будем спорить - делайте, как быстрее)
Подзапрос в запросе.
Подзапрос там "легкий" (exists) - СУБД не будет считать сикоко там записей нашлось, ни, тем паче, выдавать их клиенту.
Да и наш подзапрос ложится в Ваш индекс - вообще мелочи
insert into select Поддерживает? Замечательно! "нельзя использовать ту же таблицу, куда производится вставка." -- а мы так и не делаем.
Посмотрите на свой код.
1. Формирование списка IN в foreach - это страшно. Вот где точно тормозить должно. Если IN и используете - стремитесь к его минимальному наполнению.
2. Сперва Вы вытаскиваете (про страшность метода сказано в п.1) на клиента список существующих отелей.
Для этого заставляете СУБД просмотреть ВЕСЬ ваш список (в IN его запихнув)
3. Потом в "неинтересном коде" Вы фильтруете "вставлять/не всталять" - опять просматриваете ВЕСЬ список.
4. Потом Вы еще раз выбираете вставленные отели ... я так понимаю, что это такой же страшный IN ПОЧТИ ВЕСЬ список - часть отсеялась в п.3
Частенько встречается слово ВЕСЬ. И данные в/из СУБД гоняются многократно.
Пункт 4 убирается просто. ID записи нужно вставлять вместе с данными ... другими словами его надоть узнать ДО вставки. Для этого используются последовательности (SEQUENCE) или их имитация (в гугле полно по этому поводу http://sqlinfo.ru/forum/viewtopic.php?id=813).
В данном случае можно по другом:
Вставили одну запись;
LAST_INSERT_ID() -- узнали ID и куда надо его и ставим; (используя мой запрос .. нужно контролировать, изменилось ли значение, ибо там вставка происходит не всегда)
|
|
|
|
« Последнее редактирование: 21 Август, 2009, 09:03:05 от AndryG »
|
Записан
|
|
|
|
|