![]() |
|
Модераторы: skyboy |
![]()
|
|
| -=Ustas=- |
|
||||||
![]() Ustix IT Group ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2222 Регистрация: 21.1.2005 Где: Краснодар Репутация: 4 Всего: 69 |
Мое почтение!
Уже бесить начинает, либо просто отдохнуть надо! Дело вот в чем: В книге написано что инедксы ставятся на те поля, которые учавсвуют в WHERE условии или в ORDER BY выражении. Есть такая таблица (обрисую образно, на самом деле там таблица гораздо больше и не одна, в запросе учавствует, но этот пример за образец прокатит):
В ней более 50 000 записей. Цифра не значительная, т.к. в постгрисе пашет на ура. Далее... делабюю запрос:
Ноль реакции, EXPLAIN пишет что кеи не юзаются и using filesort, т.е. понятно что перебирает всю таблицу. Делаю такой запрос:
`created` - это int - unix_timestamp, ясно что он никогда 0 равняться не будет. Кей начинает быть заюзаным, EXPLAIN в extra показывает using where, т.е. применение индексу пошло. И выполняется моментально (ну как и должно в принципе быть). Так вот я что-то вообще не пойму эту систему, что надо делать чтоб желаемые индекированые поля были использованы в запросе? Это же не выход, добавлять голимые условия в WHERE !!! Плз, обяъсните, или ткните носом. P.S. В мане читал, и читал из этой темы http://forum.vingrad.ru/index.php?showtopi...st&p=828643 но так нифига и не понял -------------------- В искаженном мире все догмы одинаково произвольны, включая догму о произвольности догм. ----- |
||||||
|
|||||||
| muzer |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 387 Регистрация: 31.8.2006 Репутация: 30 Всего: 31 |
Вы упоминули, что в запросе участвует не одна таблица, это важно. Покажите запрос целиком.
Дело в том, что при джойне нескольких таблиц использовать индекс для сортировки уже сложнее, и он его начинает использовать только(?), если уже использует его же для WHERE (типа а почему бы не применить заодно для ORDER BY) и то не всегда (думаю, зависит от порядка джойна таблиц). А описанный пример вообще должен в обоих случаях использовать индекс. Если не хочет - можно ему сказать после имени таблицы: FORCE INDEX (имя_индекса). Это сообщение отредактировал(а) muzer - 20.9.2006, 01:35 |
|||
|
||||
| -=Ustas=- |
|
||||||||||
![]() Ustix IT Group ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2222 Регистрация: 21.1.2005 Где: Краснодар Репутация: 4 Всего: 69 |
Я тоже так думал...но...
Вот табличка:
Вот собсна сам запрос:
Выполняется где-то секунд 30. Вот результаты EXPLAIN:
-------------------- В искаженном мире все догмы одинаково произвольны, включая догму о произвольности догм. ----- |
||||||||||
|
|||||||||||
| Bikutoru |
|
||||
|
Увлекающийся ![]() ![]() Профиль Группа: Участник Сообщений: 522 Регистрация: 24.5.2005 Где: Москва Репутация: 1 Всего: 22 |
Немного не в тему, но все же:
unix_timestamp - это же неотрицательное число. Может тогда следует объявить и само поле не
а как
И такой вопрос: а чем именно обусловлен выбор int + unix_timestamp. Как я понял (из таблиц) у нас есть категории и продукты с датами создания и модификации. Мне кажется, что здесь гораздо лучше использовать тип TIMESTAMP, который обладает возможностью автоматического обновления своего значения. http://dev.mysql.com/doc/refman/5.0/en/timestamp-4-1.html Добавлено @ 11:21 Пока искал информацию о timestamp'е нашел такую вещь http://dev.mysql.com/doc/refman/5.0/en/datetime.html (см. сообщение в комментариях) -------------------- Человек, словно в зеркале мир — многолик, Он ничтожен — и он же безмерно велик! Омар Хайям |
||||
|
|||||
| muzer |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 387 Регистрация: 31.8.2006 Репутация: 30 Всего: 31 |
Что "но"? Не вижу ни одного опровержения, посмотрите explain'ы к тем запросам, которые у вас в первом примере, увидите сами. -=Ustas=-, а какой индекс он должен по-вашему использовать? Логично ведь, что сначала он выбирает категории, потом все товары из выбранных категорий, затем отбирает только активные, затем сортирует. Можно попробовать его заставить сначала товары отбирать, т.е. STRAIGHT_JOIN после SELECT написать и оставить порядок таблиц такой же. Но я всё равно не уверен, что он начнёт индекс использовать.. |
|||
|
||||
| -=Ustas=- |
|
||||
![]() Ustix IT Group ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2222 Регистрация: 21.1.2005 Где: Краснодар Репутация: 4 Всего: 69 |
Я же написал еще в первом посте результаты EXPLAIN.
Нет, я привык с INT работать. Вечером буду пробовать запросы переписывать. -------------------- В искаженном мире все догмы одинаково произвольны, включая догму о произвольности догм. ----- |
||||
|
|||||
| muzer |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 387 Регистрация: 31.8.2006 Репутация: 30 Всего: 31 |
||||
|
||||
| -=Ustas=- |
|
|||
![]() Ustix IT Group ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2222 Регистрация: 21.1.2005 Где: Краснодар Репутация: 4 Всего: 69 |
Странно, а версия мускула какая? -------------------- В искаженном мире все догмы одинаково произвольны, включая догму о произвольности догм. ----- |
|||
|
||||
| Sardar |
|
|||
![]() Бегун ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 6986 Регистрация: 19.4.2002 Где: Нидерланды, Groni ngen Репутация: 1 Всего: 317 |
А зачем должен здесь использоваться индекс, если выбираються в прямом смысле все строки. Индекс нужен для быстрого поиска, что бы эффективно/быстро откинуть большинство строк заведомо не подходящие по условию. -------------------- Опыт - сын ошибок трудных © А. С. Пушкин Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik Оценить мои качества можно тут. |
|||
|
||||
| muzer |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 387 Регистрация: 31.8.2006 Репутация: 30 Всего: 31 |
Sardar, для убыстрения сортировки (индекс-то уже отсортирован). MySQL считает, что затратнее при выборке всех строк идти по индексу и seek'ать данные из файла данных, нежели сортировать их налету при выборке. Спорить с разработчиками mysql'я не берусь, но считаю, что зависит от конкретного случая, кол-ва данных и т.д.
-=Ustas=-, я понял в чём разница, я тестировал учитывая условия вашей задачи, а вы просто абстрактный пример, так вот, если LIMIT добавить, в который написать число меньшее раза в два чем кол-во строк в таблице, то индекс подхватывается без FORCE INDEX, иначе нет.. |
|||
|
||||
| -=Ustas=- |
|
|||
![]() Ustix IT Group ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2222 Регистрация: 21.1.2005 Где: Краснодар Репутация: 4 Всего: 69 |
Хм... счас попробовал под никсами на 5-ой версии мускула, все нормально и молниеностно выполняет. В EXPLAIN правильные ключи отображает
Может быть что у меня на винде корявый мускул стоит? -------------------- В искаженном мире все догмы одинаково произвольны, включая догму о произвольности догм. ----- |
|||
|
||||
| -=Ustas=- |
|
||||
![]() Ustix IT Group ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2222 Регистрация: 21.1.2005 Где: Краснодар Репутация: 4 Всего: 69 |
Да, но суть в реальном запросе не меняется обсолютно.
Ну как зачем, для ORDER BY Вот на винде, версия 4.1.6, 20 тыс записей, запрос:
В EXPLAIN выдает filesort, сама выборка проходит около 30 сек. Вот. Этот же самый запрос на никсе, версия 5.хх, 20 тыс записей, запрос абсолютно такой же - в EXPLAIN выдает key - created, время 0.00 sec Что жу это получается, что гонки на винде? -------------------- В искаженном мире все догмы одинаково произвольны, включая догму о произвольности догм. ----- |
||||
|
|||||
| Sardar |
|
|||
![]() Бегун ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 6986 Регистрация: 19.4.2002 Где: Нидерланды, Groni ngen Репутация: 1 Всего: 317 |
Верно, видно я не выспался... Запусти ANALYZE TABLE на таблице, достаточно что бы мускул "увидел" индексы.
Может таблица в кеше была, а под виндой чего сложного делалось параллельно...... да мало ли чего может быть Запусти тест раз 50, по идее не должно быть таких разительных различий. -------------------- Опыт - сын ошибок трудных © А. С. Пушкин Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik Оценить мои качества можно тут. |
|||
|
||||
| -=Ustas=- |
|
||||||
![]() Ustix IT Group ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2222 Регистрация: 21.1.2005 Где: Краснодар Репутация: 4 Всего: 69 |
Запустил
EXPLAIN выдал тодже самое что и до этого. Не думаю, сразу после перегрузки пробую.
Тоже мысль такая была, все процессы килял, оставлял только mysqld-nt. Добавлено @ 23:14 Наверное переснесу все, по-новой поставлю. Добавлено @ 23:15 Посмотрю, что получится -------------------- В искаженном мире все догмы одинаково произвольны, включая догму о произвольности догм. ----- |
||||||
|
|||||||
| -=Ustas=- |
|
||||||||||
![]() Ustix IT Group ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2222 Регистрация: 21.1.2005 Где: Краснодар Репутация: 4 Всего: 69 |
Мужики, такой вопрос. Может чего-то не догоняю... Следуя мануалу, цитаты:
Это что, противоречие?! И что здесь в этих примерах подразумавается под key и key_part? Я сделал аналогично этому:
Т.е. :
Делаю запрос:
И он мне говорит что Using filesort. В чем дело, или я что-то не понимаю? P.S. Не пинайте сильно, и по возможности, если я не прав, объясните в чем я не прав. Или я неправильно себе представляю работу индексов?! -------------------- В искаженном мире все догмы одинаково произвольны, включая догму о произвольности догм. ----- |
||||||||||
|
|||||||||||
| sergejzr |
|
|||
![]() Un salsero Профиль Группа: Админ Сообщений: 13285 Регистрация: 10.2.2004 Где: Германия г .Ганновер Репутация: 1 Всего: 360 |
В запросах используется всегда один индех на таблицу. Этому меня умная книжка научила. Если делаешь JOIN то индех считай уже ушёл на составление таблиц. Советуют пользоваться двойными индексами, вот только пока не разбирался, но положительных результатов пока не было...
|
|||
|
||||
| -=Ustas=- |
|
|||
![]() Ustix IT Group ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2222 Регистрация: 21.1.2005 Где: Краснодар Репутация: 4 Всего: 69 |
Хм... странно вообще-то. Но индексы, поля котороых присутствуют в условии WHERE, ведь там он используется вместе?! Или я опять ошибаюсь.... -------------------- В искаженном мире все догмы одинаково произвольны, включая догму о произвольности догм. ----- |
|||
|
||||
| skyboy |
|
|||
|
неОпытный ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9820 Регистрация: 18.5.2006 Где: Днепропетровск Репутация: 41 Всего: 260 |
в смысле? никто ж не говорит, что индексы могут быть только "однопольные" - индекс может распространяться на несколько полей. Но применяться будет только один индекс. и странного я не вижу: как можно несколько индексов одновременно использовать? я не представляю |
|||
|
||||
| -=Ustas=- |
|
||||||||
![]() Ustix IT Group ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2222 Регистрация: 21.1.2005 Где: Краснодар Репутация: 4 Всего: 69 |
Хорошо. Допустим, банальный пример из выше-приведенной таблицы. Если использовать множественный индекс по правостороннему принципу (по-моему так правильно назыввается
То тогда все пучком, запрос, типа
Выполняется ИДЕАЛЬНО, с использованием этих трех индексов, Using filesort нету, и правильно. Но... тогда что получается, если мне нужен другой запрос, типа:
То я должен для этого запроса создавать отдельный множественный индекс??? Т.к. уже индекс all не используется на данный запрос. Неужели все-таки нужно создавать каждые индексы на какие-нить индивидуальные запросы? Тогда и места на диске не напасешься -------------------- В искаженном мире все догмы одинаково произвольны, включая догму о произвольности догм. ----- |
||||||||
|
|||||||||
| skyboy |
|
|||
|
неОпытный ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9820 Регистрация: 18.5.2006 Где: Днепропетровск Репутация: 41 Всего: 260 |
нету там трех индексов. ну, если принимать в расчет только
и не надо "на все случаи жизни". при нормализации по 5 НФ вообще можно обойтись только индексом на поле первичного ключа |
|||
|
||||
| -=Ustas=- |
|
|||
![]() Ustix IT Group ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2222 Регистрация: 21.1.2005 Где: Краснодар Репутация: 4 Всего: 69 |
Т.е.? 5 НФ? Да ну, не думаю что это будет оптимально -------------------- В искаженном мире все догмы одинаково произвольны, включая догму о произвольности догм. ----- |
|||
|
||||
| skyboy |
|
|||
|
неОпытный ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9820 Регистрация: 18.5.2006 Где: Днепропетровск Репутация: 41 Всего: 260 |
||||
|
||||
| Ignat |
|
|||
![]() Флудератор ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 4030 Регистрация: 19.4.2004 Где: غيليندزيك مدينة Репутация: 21 Всего: 73 |
На практике применяются, обычно, первые три нормальные формы. Пятая все же крайне нормализованная
-------------------- Теперь при чем :P |
|||
|
||||
| skyboy |
|
|||
|
неОпытный ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9820 Регистрация: 18.5.2006 Где: Днепропетровск Репутация: 41 Всего: 260 |
Ignat, зато и в самом деле - более одного индекса на таблицу понадобиться просто не может
|
|||
|
||||
| -=Ustas=- |
|
|||
![]() Ustix IT Group ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2222 Регистрация: 21.1.2005 Где: Краснодар Репутация: 4 Всего: 69 |
Какие еще формы? Пятая, третья.... Что то я вас, ребята, не понимаю Дык, а если у таблицы связей много... Добавлено @ 18:45 Такс, пошел домой книгу изучать.... Хотя главы про индексы уже перечитывал несколько раз. -------------------- В искаженном мире все догмы одинаково произвольны, включая догму о произвольности догм. ----- |
|||
|
||||
| Ignat |
|
|||
![]() Флудератор ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 4030 Регистрация: 19.4.2004 Где: غيليندزيك مدينة Репутация: 21 Всего: 73 |
Значит таблица не находится в 5НФ
Почитай лучше теорию реляционных БД ;) -------------------- Теперь при чем :P |
|||
|
||||
| skyboy |
|
|||
|
неОпытный ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9820 Регистрация: 18.5.2006 Где: Днепропетровск Репутация: 41 Всего: 260 |
||||
|
||||
| muzer |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 387 Регистрация: 31.8.2006 Репутация: 30 Всего: 31 |
Сколько у вас строк в таблице, что вы так боитесь filesort'а?
Когда объём данных переваливает за тот предел, при котором ORDER BY без индекса реально тормозит и исправить это разумным кол-вом индексов нельзя - нужно задуматься о создании избыточности данных, путём хранения в разных таблицах одного и того же в разном разрезе с разными индексами. sergejzr, как было выяснено несколькими топиками ниже - пятая версия mysql умеет использовать несколько индексов от одной таблицы. Считаю, нормальные формы нужно знать, чтобы уметь правильно мыслить при проектировании базы данных. Больше нормальные формы ни для чего не нужны, т.е. нельзя их в чистом виде использовать для построения бд. Это сообщение отредактировал(а) muzer - 28.9.2006, 21:34 |
|||
|
||||
| skyboy |
|
|||
|
неОпытный ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9820 Регистрация: 18.5.2006 Где: Днепропетровск Репутация: 41 Всего: 260 |
что понимается под "чистым" видом? насколько часто необходимо идти "вразрез" с первой НФ(насколько я помню - это требование к "атомарности" единицы данных - поля)? |
|||
|
||||
| muzer |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 387 Регистрация: 31.8.2006 Репутация: 30 Всего: 31 |
Под чистым видом понимается приведение структуры БД строго к какой-либо нормальной форме. На практике чаще всего есть частичное соответствие той или иной НФ, но т.к. определения НФ не подразумевают частичного соответствия, то я и говорю, что они служат только для развития мышления.
Хм..приходится. Когда нужно хранить список значений (являющихся праймари в другой таблице) переменной длины без необходимости использовать его в джойнах. Например, данные для загрузки в какую-либо программу. Хранить "вертикально" - очень затратно, большой объём получится, неповоротливая таблица. Это сообщение отредактировал(а) muzer - 29.9.2006, 01:40 |
|||
|
||||
| skyboy |
|
|||
|
неОпытный ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9820 Регистрация: 18.5.2006 Где: Днепропетровск Репутация: 41 Всего: 260 |
muzer, не знаю, не знаю... одно дело - так хранить строки, другое дело - ключи... если по ним присоединять вообще ничего не надобно - то на кой их хранить? а если надо будет присоединять - то конструкция REGEXP не настолько быстра, чтоб заменить джойн по равенству...
Добавлено @ 08:38 muzer, слушай, опиши структуру, при которой поребуется уйти от атомарности |
|||
|
||||
| -=Ustas=- |
|
|||
![]() Ustix IT Group ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2222 Регистрация: 21.1.2005 Где: Краснодар Репутация: 4 Всего: 69 |
Да уже читаю skyboy, спасибо за ссылку на статью. Погрузился в чтение )) -------------------- В искаженном мире все догмы одинаково произвольны, включая догму о произвольности догм. ----- |
|||
|
||||
| Grasshopper |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 31 Регистрация: 23.3.2006 Репутация: нет Всего: 1 |
при связи много-ко-многим создается отдельная таблица с двумя индексными полями - ключ от одной таблицы и ключ от другой. Другие решения представляются ГОРАЗДО более затратными по скорости |
|||
|
||||
| skyboy |
|
|||
|
неОпытный ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9820 Регистрация: 18.5.2006 Где: Днепропетровск Репутация: 41 Всего: 260 |
||||
|
||||
| muzer |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 387 Регистрация: 31.8.2006 Репутация: 30 Всего: 31 |
Grasshopper, при связи многие ко многим не всегда обязательно иметь возможность выбирать эти данные одним запросом и именно в базе. Но нужно иметь возможность быстро редктировать один из наборов.
skyboy, приведу пример похожий на реальный, но применив другую тематику, а то получится разглашение представь, есть огромная база голосований: вопрос и несколько вариантов ответов. с одной стороны есть интерфейс их редактирования, с другой стороны есть движок, который на входе имеет некое условие, по которому отбирает вопрос, на выходе должен вернуть вопрос и все его ответы. Делать селект из двух джойнов на каждый запрос - нет смысла, не живёт, нагрузка например неск сот запросов в секунду, вопросов 5 миллионов за всю историю, ответов соответсвенно раз в 10 больше (если в одной таблице хранить индексы, то это будет 5 млн х 50 млн = 500 млн...это не для MySQL'я). Понятно что ответы повторяются, их например 2 млн. Т.е. если загружать всё это по отдельности в память движка, в хэши и т.п., то решаются все поставленные задачи - мы можем быстро отвечать на запрос, мы можем быстро редактировать список ответов. Выбрать всё и сразу - такой задачи не стоит. |
|||
|
||||
| skyboy |
|
|||
|
неОпытный ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9820 Регистрация: 18.5.2006 Где: Днепропетровск Репутация: 41 Всего: 260 |
не понял. если под "каждым запросом" имелся в виду отдельный вопрос, то мы же с самом начала выберем только один конкретный вопрос и "всего" не будет. если под "каждым запросом" имелся в виду набор вопросов("анкета"), то внеся в базу структуру этой "анкеты" из логики работы обрабатывающей программы, мы получим возможность выбирать только то, что нам надо,опять же - без декартового произведения. может, я неверно понял, тогда растолкуй, если не сложно. а может - после "неразглашения" и "смены тематики" пример утратил адекватность? |
|||
|
||||
| muzer |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 387 Регистрация: 31.8.2006 Репутация: 30 Всего: 31 |
может и утратил, но попробую..
Давай будем по этапам. Какая структура по нормализации должна быть? Три таблицы, правильно? T1. QuestionID | bla bla bla T2. AnswerID | bla bla bla T3. QuestionID | AnswerID Сколько строк будет в таблице T3, если мы рассматриваем приведённый пример? 500 млн.. Выбрать нужно по какому-то bla-bla вопрос, и все его ответы. Т.е. SELECT .. FROM T1 INNER JOIN T3 USING(QuestionID) INNER JOIN T2 USING(AnswerID) WHERE T1.bla... |
|||
|
||||
| skyboy |
|
|||
|
неОпытный ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9820 Регистрация: 18.5.2006 Где: Днепропетровск Репутация: 41 Всего: 260 |
а. теперь понял, что тебя смущает. только, во-первых, если речь о максимальном объеме таблицы, то можно разбить третью таблицу на несколько таблиц. Забыл, как этот процесс называется
Да, там можно ещё один столбец в третью таблицу, указывающий на порядок ответа в списке. Или на "вес" ответа. Или на признак "верности"(впрочем, нет - лучше это в четвертую таблицу). а если загонишь в одну строку типа "1, 2, 5, 29", то попробуй потом посчитай без REGEXP, какой ответ используется наиболее часто... Да, согласен с мыслью, что в зависимости от задачи может быть и рационально отступать от НФ, но, как на меня, пример не подтверждает это утверждение Добавлено @ 00:14 "репликация", что ли... черт, не буду больше пить пиво |
|||
|
||||
| muzer |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 387 Регистрация: 31.8.2006 Репутация: 30 Всего: 31 |
А вот тут неточность Сколько занимает времени подобная выборка вопрос не самый важный, самый важный вопрос - насколько быстрее будет работать схема не по НФ. Ответ - в десятки раз быстрее. А это значит, что требуется для работы ставить в десятки раз меньше серверов или сервера могут быть менее мощные. Разбить таблицу на несколько можно, но это уже кластеризация, причём даже в текущем примере по непонятному признаку, а следовательно усложнение системы в разы. (репликация - это некая схема объединения баз данных, когда, например, одна база зависит от другой (односторонняя репликация)) |
|||
|
||||
| skyboy |
|
|||
|
неОпытный ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9820 Регистрация: 18.5.2006 Где: Днепропетровск Репутация: 41 Всего: 260 |
не знаю, не зна... там - работа со строками, при НФ - работа с индексами по числам. Протестировать не получилось: только НФ-ый вариант. Выбор 3 строк из 236000 заняло горздо меньше секунды |
|||
|
||||
| muzer |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 387 Регистрация: 31.8.2006 Репутация: 30 Всего: 31 |
Где работа со строками? В коде на cи? Сделать SELECT *, распарсить, сложить в нужные структурки и готово.
Из 236 тысяч меньше секунды, ессно. А из 500 млн? даже из 100 млн.. И не забывай, что в несколько потоков. |
|||
|
||||
| skyboy |
|
||||
|
неОпытный ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9820 Регистрация: 18.5.2006 Где: Днепропетровск Репутация: 41 Всего: 260 |
muzer, в смысле? склепай запрос, который при ненормализованном хранении соответсвий ответов и вопросов вытягивает список ответов для заданного вопроса. НЕ парсить строку "1, 2, 10, 30" на стороне клиента и динамическое формирование соотвествующимх запросов к таблице, а plain-SQL.
Добавлено @ 21:52 пущай таблица вопросов: questions idquestion(int autoinc) title(varchar) answers(varchar) - номера ответов через разделитель answers idanswer title ________________ нормализованная форма: questions idquestion(int autoinc) title(varchar) answers idanswer title questions_answers idquestion idanswer ________________ Для нормализованной формы:
Для ненормализованной ситуации(на REGEXP'ах):
Можно и без REGEXP'a, но лениво ______________ Как думаешь, что быстрее будет? |
||||
|
|||||
| Ignat |
|
|||
![]() Флудератор ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 4030 Регистрация: 19.4.2004 Где: غيليندزيك مدينة Репутация: 21 Всего: 73 |
Притянуто за уши, но для примера. Имеются две таблицы: В одной какие-либо события, допустим котировки акции, скажем пару миллионов записей. Во второй какое-то конечное число других сущностей, к примеру, наименования бирж, на который торгуются акции, число ограничено десятком. Нам нужно выбрать строки с событиями, а также связать с таблицей бирж. Первый вариант (таблицы находятся в нф): вводим таблицу для связей, при этом количество строк грубо = (количество котировок*AVG(количество бирж для каждой акции)), связываем по ключам min 2 джойна при выборке 2-х миллионов строк(!). Вариант кошерный, но не оправданный. Вариант второй: список бирж через разделитель сохраняем в каждой строке Выбираем все записи из таблицы бирж, храним в памяти. Выбираем котировки без джойнов. При анализе, в случае необходимости парсим строку и связываем с наименованиями, которые уже(!) находятся в памяти. skyboy, как думаешь, какой вариант быстрее? Хоть это натянутый пример, но такое встречается чаще, чем хотелось бы. -------------------- Теперь при чем :P |
|||
|
||||
| skyboy |
|
|||
|
неОпытный ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9820 Регистрация: 18.5.2006 Где: Днепропетровск Репутация: 41 Всего: 260 |
Ignat, принято, хоть и притянуто. Только если "отталкиваться" от котировок. А если от бирж - посмотрим, что будет быстрее. И ещё вопрос: как ты, к примеру, отбросишь все котировки, которые не котируются на определенной бирже? или наоборот - котриуются? вообще, почти любое условие по отбору, которое в случае НФ уменьшало бы количество строк в разы, при не-НФ форме превратится в мегатонны головной боли
Добавлено @ 11:29 Ignat, ха! ты из тонкого клиента одним движением сделал толстого! попробуй вернуться к тонкому клиенту и написать запрос типа моего(только у меня - REGEXP$ не лучшее решение), и посмотрим, кто - кого. Ведь маловероятно, чтоб набор котировок был конечным этапом - потом будет группировка вычисление кучи статистичесих параметров... |
|||
|
||||
| muzer |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 387 Регистрация: 31.8.2006 Репутация: 30 Всего: 31 |
skyboy, вот Игнат очень точно описал то, что пытался я
И как показывает практика, статистики намного меньше, чем множество всех возможных вариантов. Т.е. статистику имеет смысл хранить отдельно. В случае примера с голосованием, будет большое кол-во вопросов, на которые никогда не отвечали, будет большое кол-во ответов в некоторых вопросах, которые никогда не выбирали. Для них не имеет смысл хранить нули, лучше просто не хранить ничего. |
|||
|
||||
| skyboy |
|
|||
|
неОпытный ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9820 Регистрация: 18.5.2006 Где: Днепропетровск Репутация: 41 Всего: 260 |
вернемся к вопросам-ответам. мне надо выбрать все ответы для вопроса №23. я запуская запрос с двумя join'ами(если мне надо ещё и название вопроса) и получаю результат. или я запускаю запрос к базе, выдираю вопрос №23. парсю строку с описанием списка ответов и запихиваю номера в массив. потом обращаюсь к базе и получаю по номерам нужные мне ответы. так, что ли? я правильно понял? |
|||
|
||||
| Ignat |
|
||||
![]() Флудератор ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 4030 Регистрация: 19.4.2004 Где: غيليندزيك مدينة Репутация: 21 Всего: 73 |
Да, но только не надо понимать буквально и на каждый ответ генерить запрос к БД. Достаточно собрать нужные ответы в конструкцию:
и выполнить один запрос. -------------------- Теперь при чем :P |
||||
|
|||||
| skyboy |
|
|||
|
неОпытный ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9820 Регистрация: 18.5.2006 Где: Днепропетровск Репутация: 41 Всего: 260 |
Ignat, но парсинг строки происходит на стороне клиента! то есть данные надо прогнать в одну сторону, выделить под них буфер, записать, а потом - обратно. уверен, что будет быстрее?
Добавлено @ 18:44 Ignat, значит, по-твоему, IN (подмножетсво) выполняется медленне INNER JOIN по первичному ключу? хм... |
|||
|
||||
| Ignat |
|
|||
![]() Флудератор ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 4030 Регистрация: 19.4.2004 Где: غيليندزيك مدينة Репутация: 21 Всего: 73 |
Всё зависит от количества строк и использования индексов. Есть случаи оправданной "денормализации". -------------------- Теперь при чем :P |
|||
|
||||
| skyboy |
|
|||
|
неОпытный ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9820 Регистрация: 18.5.2006 Где: Днепропетровск Репутация: 41 Всего: 260 |
Ignat, конечно. пролистай страницу и убедись, что я не фанат.
но в приведенном тобой примере количество бирж должно быть просто нереально малым, чтоб оправдать обработку на стороне клиента(2-3), если больше, то уже должно быть нехорошо... И в примере muzerа тоже не все однозначно. Точнее, далеко не однозначно. Я ж не спорю с тем, что панацеи не бывает. Я просто желаю получить "жЫзненный" пример, когда денормализация - единственный выход, а НФ тормозят роботу с БД. Добавлено @ 19:08 Ignat, а IN разве будет быстрее UNION ALL? Добавлено @ 19:09 вопрос снимается. на самом деле, может быть быстрее, а может и нет. при UNION несколько сканирований, при IN(как мне кажется) не применяются ключи. Добавлено @ 19:14 ошибся. применяется. наверное, "разворачивается" в UNION. |
|||
|
||||
| Ignat |
|
|||
![]() Флудератор ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 4030 Регистрация: 19.4.2004 Где: غيليندزيك مدينة Репутация: 21 Всего: 73 |
Совсем не 2-3, но, спешу заметить, бирж и так не много На самом деле если число заведомо ограничено, до сотни строк в подчиненной таблице, то имеет смысл подумать о том, чтоб хранить её в памяти. Например, список регионов, областей, бирж, валют и т.д. Я тоже не фанат, сам предпочитаю хранить в НФ, но повторюсь: таких случаев больше, чем хотелось бы. -------------------- Теперь при чем :P |
|||
|
||||
| skyboy |
|
|||
|
неОпытный ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9820 Регистрация: 18.5.2006 Где: Днепропетровск Репутация: 41 Всего: 260 |
а кеширование-то при чем? что мне мешает загрузить ответы, которые используются более, чем в 40% вопросов в память? что мне мешает записать все биржи у клиента и "делать JOIN" на стороне клиента, чтоб разгрузить базу? только каким боком использование и концепция кеша к НФ? |
|||
|
||||
| skyboy |
|
|||
|
неОпытный ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9820 Регистрация: 18.5.2006 Где: Днепропетровск Репутация: 41 Всего: 260 |
ещё одно "ЗА" для НФ: в MySQL при помощи group_concat можно "перейти" от НФ к неНФ, а обратное "преобразование на лету" невозможно
Добавлено @ 00:10 надо бы в holy wars скинуть часть, а то разошлись тута слегка |
|||
|
||||
| muzer |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 387 Регистрация: 31.8.2006 Репутация: 30 Всего: 31 |
Как-то получилось много абстракций.
Давайте чётко определим, на какие вопросы хотим ответить. Я вижу следующие: 1. Какой должна быть система, удовлетворяющая след критериям: минимальное время ответа, возможность изменять списки. Два варианта решения: а) сделать всё в базе по НФ с помощью трёх таблиц. Минусы:
Минусы:
2. Быстрее парсить и делать несколько селектов или довериться джойну? Для меня ответ однозначен - быстрее парсить и делать несколько селектов. Проверно многократно на больших данных. Кто сомневается, можете тестить..увы голыми словами я этого не докажу. skyboy, Жизненный пример: сеть контекстной рекламы на разных сайтах, типа Бегуна, гугл эдсенс и т.д. Есть страница какого-то вёбмастера, который установил у себя блок рекламы. Робот сети определил для этой страницы набор ключевых слов, по которым должна отбираться реклама. Задача: когда посетитель зашёл на сайт, нужно показать n объявлений. Чтобы найти объявления, нужно узнать ключевые слова для этой страницы. Что проще, выбрать одну строку со списком слов или выбрать десять строк по слову на строку? Сколько в инете страниц? Миллионы, миллиарды, сколько в среднем слов определяется на каждую страницу? Пусть десяток.. Где и как хранить миллионы помноженные на десяток слов? |
|||
|
||||
| skyboy |
|
||||
|
неОпытный ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9820 Регистрация: 18.5.2006 Где: Днепропетровск Репутация: 41 Всего: 260 |
muzer, надеюсь, твой пример - это не разглашение? :-|
не мог бы поподробнее описать, какой алгоритм ты имеешь в виду по "парсингом", чтоб я точно не обознался, и я протестирую.
как это выглядит? рекламный блок N связан со словами "world", "hello" и "happy", а страница M ассоциирована со словами "tree", "frieands" и "world" - потому и возникает соотвествие и реклама N отображается на сайте M? Т.е. определение пересечения подмножества? или четкое совпадение? если четкое совпадение требуется, могут ли слова в строке для блока и для сайта иметь разный порядок? хороший вопрос. положим, используем неНФ форму. Что хранится в неатомарном поле? списк индексов слов или(о, Боги!) сами слова? если сами слова, то на хранение требуется намного больше места, чем НФ-варианта. Впрочем, я так, с перепугу предположил. Не думаю, что так кто-нить делать будет при миллионе строк. Хотя... в среднем на такое поле из 10 слов 100 символов + 11 на идентификатор = 111 байт на строку или 111 * (количество сайтов == 1 000 000) = 100 Mb. Но не надо хранить слова. Но и группировка по словам такая, что проще застрелиться. И безопаснее для мозга. Возьмем вариант, где в неатомарном поле хранятся индексы. 10 индексов по 10 символов + 9 символов-разделителей = 29 байт + 11 байт идентификатора = 40 байт на строку * (количество сайтов == 1 000 000) = 35 Mb. Примемся за НФ-вариант. на каждую строку: 11 + 11 = 22 байта, строк на сайт == 10, т.е. 220 байт; плюс отдельно хранятся идентификаторы сайтов(по 11 байт на сайт), где эти идентификаторы генерируются. Итого - 231 байт на сайт. 231 * (количество сайтов == 1 000 000) = 220 Mb. В самом деле, более, чем в два раза больше, чем для случая, когда записываем САМИ СЛОВА в таблицу. А ведь была ещё забыта таблица слов... Вот такая она, НФ-форма. |
||||
|
|||||
| muzer |
|
||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 387 Регистрация: 31.8.2006 Репутация: 30 Всего: 31 |
В неатомарном поле хранятся, конечно же, индексы. В отдельной таблице хранится словарик соответствия индекса и слова. Что я имел ввиду под парсингом: SELECT word_id_list FROM table; (разделитель в неатомарном поле - запятая) SELECT word FROM dictionary WHERE word_id IN (word_id_list); Это простейший пример. Только с помощью базу и простейшей обёртки. На деле же обе таблицы грузятся в память, ну а дальше всё то же самое только в синтаксисе языка. По какому алгоритму идёт сравнение слов тут даже не важно, это другая задача. Все необходимые для сравнения цифры ты, в общем-то, сам уже привёл |
||||
|
|||||
| skyboy |
|
|||
|
неОпытный ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9820 Регистрация: 18.5.2006 Где: Днепропетровск Репутация: 41 Всего: 260 |
не все. объем - это не единственный параметр оценки. надо ещё скорость сравнить. только это будет зависеть от задачи. например, клиент - на удаленном компе, база - на сервере, имеющем IP. что мне лучше - передавать на клиента данные и ждать, пока он их распарсить и затребует другие данные, или самому распарсить? думаю, второе. вобщем, от канала очень сильно зависит. да и при работе PHP на том же сервере тоже может случиться, что быстрее будет СУБД парсить, чем работать с массивами в PHP. а убеждать меня не надо, сам знаю о вреде фанатизма. я просто ждал "универсального" примера, который сам по себе в отрыве от условностей вроде скорости передачи данных "обязывал" бы использовать неатомарные данные. но, наверное, такого примера быть не может. ну, и ладно Добавлено @ 15:16 ещё заметка: у неатомарного хранения большое ограничение: нельзя определить характеристики связей, если они есть. Например(для "вопросов - ответов") нельзя определить "вес" ответа и прочие характеристики(кроме порядка, пожалуй, потому как в неатомарном поле порядок как раз задан). Это просто, заметки на полях. |
|||
|
||||
| muzer |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 387 Регистрация: 31.8.2006 Репутация: 30 Всего: 31 |
php не входит в список языков, которые я подразумевал
си, питон, ява на худой конец.. перл и пхп не для этих целей. про разнесённые на диал-ап сервера мы тоже не говорим про цифры - объём конечно не единственное. но помимо объёма уже недонократно обсуждали, два джойна делать. |
|||
|
||||
![]()
|
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | MySQL | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |