Вопросы Эффективности и Быстродействия

Lord Max

Guest
Вопросы Эффективности и Быстродействия

Доброго времени суток Пиплы!

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

Вопрос №1___Использование Foreign key или огромной таблицы.
У меня есть БД, в которой есть таблица пользователей с паролями, уровнями доступа, персональной информацией, статусом, полями информации для статистики и тд. (всего 68) А так же есть таблица (часто используемая) с вещами этих (существующих) пользователей, то есть по-сути идёт дублирование полей пользователей. Вопрос такой, как поступить, разбить таблицу пользователей на тематические: личная инфа, списки вещей, данные статистики и тд, при этом количество запросов возрастёт соответственно, или же слить ВСЕ, что касается пользователей в 1 большую таблицу, даже если количество полей перегребёт за 100 и ‘селектать’ конкретные поля для разных страниц проекта (там, где требуется инфа по статистике – поля статистики, там, где список вещей – список вещей и тд.) Где правда ? Какой из вариантов наиболее эффективный, если подразумевается не ‘сильный’ сервер и большое количество обращений. Что «тормозит» при создании 100 и более полей в таблице? Может у меня банан в мозгу и можно просто использовать сложный запрос ? В какую сторону смотреть ?

Вопрос №2___Злоупотребление функцией Split.
Подоснова этому вопросу предыдущий вопрос. В целях уменьшения количества полей, я очень часто пишу в поле тематически схожие данные, чтобы затем «распилить» их сплитом. Насколько этот выход оправдывает себя ? Может лучше отказаться от сплита и это снизит время выполнения скрипта ? Но тогда количество полей увеличится в разы!

Вопрос №3___MySQL  Кириллица  PHP  Flash
Возможно, Вы знаете как это правильно делается. Используя юникод у меня получается «забить» во flash русские буквы, но вот переменная из БД этого делать не хотит и выводит во флэше полную лажу 

Вопрос №4___Индексы
Оправдано ли использование большого количества индексов для различных целей, разумеется, для поиска конкретных записей, или же лучше постараться обойтись парой-тройкой?

Вопрос №5___VARCHAR или TEXT
Стоит ли пользоваться длинным (80 и более символов) VARCHAR, если данные в этом поле могут быть и длинными и короткими, что «ест» больше памяти, что более эффективно?

Вопрос №6___mysql_close();
Нужно ли в конце каждого скрипта закрывать соединение с БД ? Или это делается автоматом ? Какие ресурсы освобождаются ? Или освобождаются ли ?

Вопрос №7___Большие массивы
Сильно ли тормозит выполнение скрипта большой массив «гуляющий» по функциям и методам классов ? Или стоит задуматься над сокращением ? Можно ли передавать функции весь массив, если из него требуется только несколько элементов или же лучше передавать нужные элементы отдельно ?

P.S. У меня Apache (ver2) + MySQL (ver4) + PHP (ver5) под виндой.
P.S.S. Я полностью отдаю себе отчёт в том, что много из того, что я спрашиваю является базисом, но у меня есть оправдание, многое пришлось учить на ходу с полного «0». И я решал проблемы по мере их поступления, то есть узконаправленно шёл к достижению конкретной цели. В идеале я должен был полностью изучить специфику mysql и php от самых основ, тогда, возможно и не задавал бы глупых вопросов, но нехватка времени привела к тому, что я имею кучу пробелов в знаниях, которые возможно, Вы мне поможете заполнить. Буду рад любому ответу, лишь бы в тему.
 

kos

Новичок
не претендую на звание гуру, но свое мнение выскажу, вполне могу ошибаться
№1
информацию нужно создавать на таблицы исходя из её назначения и структуры т.е.
Разделить пароли и уровни доступа в одну, личную инфу фио, тел... в другую из-за того, что она используется в разных целях.
Отделить статистику необходимо еще из-за неудобства её хранения в таблице с login и др. Например, как писать посещения в одно поле через разделитель? если хотите большой гемор пожалуйста.. надо создать таблицу типа id id_user date
при правильно подходе использовать эти данные одновременно не придется, а если и нужно то sql можно одновременно выбирать хоть из 100 таблиц
И поищите по yandex про нормальные формы
№2
Не делайте так, хотя бы потому что через месяц (ну или больше у кого какая память) вспомнить что где и зачем будет сложно
№3
В php есть функции перекодировки по моему в разделе строковых функций
№5
VARCHAR использует столько памяти, сколько записано в поле, я всегда делаю 255
№6
лучше использовать, но не принципиально
№7
нужно максимум операций переложить на mysql и получать данные готовые к использованию, всегда когда возможно, а возможно почти всегда. у меня обычно 60-70% кода сборка запросов
 

alexhemp

Новичок
Lord Max

1. Читайте учебник по теории реляционных БД и нормальные формы. В общем случае нужно избегать дублирования данных. Хотите привязать информацию к пользователю - вставьте ссылку (идентификатор). Для разных типов связей потребуется создавать разные таблицы.

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

3. Перекодируйте данные перед выводом в нужную кодировку - это элементарно.

4. Почитайте руководство MySQL - там написано как нужно создавать индексы. Индекс должен соответствовать типовому запросу.

5. Эффективнее использовать CHAR для коротких строк и *TEXT для больших текстов. В руководстве mysql об этом сказано.

6. Не нужно. php сделает это сам, "чистя мусор" после скрипта.

7. Изучите работу php с памятью. Насколько "большой" у вас массив? 10килобайт? 100 или сотня мегабайт.
В общем случае стоит передавать ССЫЛКУ на большой массив, а не сам массив.
 

Lord Max

Guest
Спасибо за Ваши ответы.
To kos
Только 1 вопрос по пункту №7
Не будут ли эти максимум Mysql операций работать медленнее чем аналог с обработкой данных PHP при большом количестве обращений к странице ?

To alexhemp
№1
Всё равно не понимаю.. :( Я знаю, что прочитав учебник, я не задал бы те вопросы, которые задаю, но форум же существует, как мне кажется, не для того, чтобы задающим говорили прочитать учебник, это и так понятно, я специально написал, что мне нужен ответ именно на конкретный вопрос. А вопрос такой : Как реализовать выборку данных одним запросом, если у меня таблица пользователей с основной информацией и 3 тематические таблицы( инвентарь, статистика, другие данные) количество ? Понятно , что все данные не будут использоваться во всех случаях, всегда используются только основные данные о юзере. Почему я не могу сделать таблицу из 100 полей и выбирать разные данные на разных страницах, тем самым у меня будет 1000 полей для 1000 пользователей а не 5000 при 5ти таблицах
№2
Чем я нагружаю SQL сервер, если эти поля лишь хранят динамический контент и выборка по этим полям не осуществляется.
№7
Массив, скажем, до 100 элементов, одномерный, ссылка поможет в случае функций, а вот как быть с методами ? Полагаю, что необходим код, где идёт выборка данных и дальнейшее использование их реализуется в пределах 1 класса. У меня есть класс авторизации, который присутствует на большинстве страниц, 1 из методов производит коннект, другой метод сверяет кукис и при наличии пользователя возвращает массив. Так вот это массив я затем использую в другом классе или даже классах, относящихся к конкретной странице. В чём недостаток того как я вижу процесс ?
 

alexhemp

Новичок
Lord Max

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

Поими, SQL сервер создается с использованием теории РСУБД и следовать ей при проектировании базы - значит облегчить себе жизнь, не наступая на грабли. Количество граблей большое, почитай форум.

Форум существует не для того, чтобы отвечать тебе на вопросы на которые ДОЛЖЕН отвечать учебник.

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

7. Что тебе мешает получив массив - дальше передавать ссылку на него? Или запиши его в глобальные переменные.
 

kos

Новичок
Lord Max
sql однозначно быстрее(за редкими исключениями) если правильно базу спроетровать.
попробуйте пройти циклом массив из 40 000 - 50 000 элементов.. мой бук умирает при 20 000
 

Lord Max

Guest
to alexhemp
1
Тогда просто скажите, можно ли использовать таблицу где 100 и более полей и на разных страницах выбирать селектом нужные данные ?
2
SELECT * from...WHERE id = индексированное поле
вот там (*) и идут поля с данными через точку - я это имею в виду, а храню для того, чтобы использовать их :)
 

alexhemp

Новичок
Lord Max
1. Можно делать все. Только глупо использовать 100 полей в таблице - такое их количество говорит о неверной структуре базы.
Какие данные вы там храните?

2. То-же самое. Скорее всего у вас там список значений. Если потребуется в будущем сделать скажем "фильтр" значений, у вас ничего путного не выйдет.
Почитайте на форуме темы по поиску товаров по параметрам - все поймете.

Вот почитай - показательный пример глупого подхода
http://phpclub.ru/talk/showthread.php?s=&threadid=73162&highlight=%F5%F0%E0%ED%E5%ED%2A+%EF%E0%F0%E0%EC%E5%F2%F0%2A

а вот грамотный человек грамотно хранит параметры товаров (на любой товар их может быть произвольное переменное число - при этом структура базы - не меняется никак)
http://phpclub.ru/talk/showthread.php?s=&threadid=65869&highlight=%EF%EE%E8%F1%EA+%EF%E0%F0%E0%EC%E5%F2%F0%2A

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

Убеждать больше не буду - хочешь биться головой об стену - бейся.
 

Falc

Новичок
Lord Max
Дам несколько общих советов.

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

Хранить несколько обектов в одном поле, с точки зрения теории РБД не верно, но может быть оправдано сточки зрения производительности, все зависит от конкретного проекта.

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

По поводу индексов, индексов должно быть ровно столько сколько нужно, не больше и не меньше, не надо делать индексы на авось пригодится. Если в над таблицей производится много изменений критичных к быстродействию, то нужно минимизировать кол-во индексов. По своиму опыту скажу что много индексов бывает нужно очень редко, часто удается заставить большинство запросов использовать одни и теже индексы. Т.к. MySQL кеширует индексы то нужно старатся чтобы объем индексов был как можно меньше, тогда в кеше вместится больше данных из индексов и следовательно система будет работать быстрее. Если узким местом является дисковая подсистема, то может оказатся очень полезным вынос в индекс всех полей таблицы, чтобы при индексном сканировании не было обращения к таблице, что может значительно уменьшинь кол-во дисковых операций.

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

Lord Max

Guest
to alexhemp && Falc

Я доверяю Вашему мнению, так как ещё не силён в сложном проектировании, однако запросы у меня больше текущих знаний. Моя цель – интерактивная онлайн игра для меня и моих друзей. Предел мечтаний превратить когда-нибудь её в коммерческий продукт. Я избрал практическую разработку для освоения php и mysql , у меня есть несколько книг по php включая переведённое издание Wrox Press «Профессиональное PHP программирование». Всё, что знаю о mysql черпал оттуда + мануал.
Итак : В таблице пользователей у меня всевозможная информация относящаяся к каждому зарегистрированному пользователю, все пользователи имеют в каждом из полей какое-то значение, будь-то уровень или навык или время последнего действия персонажа. Кстати о навыках, например : название навыка\поля – «Навигация», у каждого нового персонажа там значение через запятую 0, 0 (уровень навыка, текущий опыт) Или же поле – к котором у каждого пользователя содержится список известных (ему лично) систем (id-[PK] другой таблицы). Короче говоря, ВСЕ поля используются каждым пользователем и у каждого пользователя может быть ровно столько полей, сколько их в этой таблице. Ни у кого не может быть 2 навыка «Навигация» или ещё чего-либо. Поэтому я сделал вывод, что использовать 5 таблиц нет никакого смысла, так как в любом случае в каждой из этих таблиц будет ОДИНАКОВОЕ количество строк, РАВНОЕ количеству пользователей, ни больше, ни меньше. А вот объемные логи каждого из персонажей, я вынес в отдельную таблицу, так как у каждого их может быть разное количество и объём.
Пожалуйста, объясните мне, зачем разбивать большую таблицу на 5 (увеличивая тем самым количество строк в 5 раз) и выбирать данные используя вспомогательные таблицы или Join в запросе ???

Про хранение нескольких объектов в одном поле (есть у всех пользователей) :
«Эндора,Шатл,n2,0,11» – поле корабль
«Пистолет 9мм.weapon.40.40.35.0.пусто.-.NA.-.пусто.-.NA.-.пусто.-.9mm» – поле оружие (причём в каждой руке может быть по такой вот записи) Все эти данные уникальны для каждой единицы оружия\брони , да и любого предмета. Уникальны потому, что каждая единица может, путём модернизации, иметь завышенные или заниженные параметры, отличающиеся от первоначальных – на момент выпуска с завода. Например : можно ставить оптику, глушитель, улучшать точность стрельбы – для оружия, но уменьшает дальность выстрела, и др. для других предметов.

PS К тому же, в режиме боя, мне нужно выбрать данные сразу по 20(10х10-максимум) пользователям. Это все данные, которые отвечают за их боевые характеристики. И мне нет необходимости идти методом «выборки товаров», у меня у каждого пользователя есть определённые поля, у всех одни и те же. (прочитал обе темы по ссылкам)
 

Falc

Новичок
Lord Max
Если цель твоего проета - самообразование, то тебе лучше все делать по теории. Для начала тебе нужно привести базу в 3-ю нормальну форму, тогда у тебя получится кравивая структура из нескольких табличек и не будет таблиц с сотней полей. И перед тем как что-то начинать делать в базе рекомендую на бумажке набросать хотябы примерную схему данных.
 

Lord Max

Guest
To Falc
1
Что Вы можете сказать по-поводу хранения мной нескольких объектов в одном поле ? (согласно тому, что я написал выше)
2
Прочитал немного теории ... Если Вам не сложно, объясните пожалуйста, почему я не вижу почвы для нормализации: все поля моего отношения (таблицы пользователей) чётко привязаны к ключевой связке [id + username]. Никакого дублирования данных не происходит, выборка данных идёт путём элементарного запроса с указанием нужных полей для выборки, используя индексы. Обновления осуществляются часто , но опять же, используя индексы и для нескольких полей отношения. Удаления записей не происходит вовсе. Добавление новой записи : абсолютно не трогая другие таблицы, вставляю новую запись в таблицу пользователей (причём вставляю только username + pass, id авто инкрементируется, а все остальные поля, которых около 100 , устанавливаются на значения по–умолчанию таблицы ). С точки зрения теории я с Вами полностью согласен, стоит перечитать многое и привести всю базу отношений к 3й форме, НО я задаю вопросы только относительно таблицы пользователей. Так получилось, что у каждого пользователя (у меня) существуют такие персональные свойства как пол, кол-во игровых денег, уровни и тд. В каждом из них ( в теории ) могут быть уникальные значения, на практике, конечно, дублируется пол, могут уровни , кол-во денег, опыта , и тд. У меня могло быть только 10 свойств пользователей, но у меня их 100, что тут нормализировать ? :) ПОЖАЛУЙСТА объясните чайнику…
 

SelenIT

IT-лунатик :)
Пистолет 9мм.weapon.40.40.35.0.пусто.-.NA.-.пусто.-.NA.-.пусто.-.9mm
Оставим пока в стороне тонкости различий между "пусто", "NA" и прочерком. Но неужели удобно заставлять DB-сервер выбирать и отсылать клиенту кучу текста, над которым еще нужно произвести серию нетривиальных преобразований, чтобы в итоге получить n раз "пусто"? И как в такой схеме, например, сравнить две пушки по дальнобойности?
 

alexhemp

Новичок
Lord Max

Ты неверный выбрал путь для хранения полей твоего "объекта".

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

Я уже давал ссылку на то, как нужно правильно хранить параметры: http://phpclub.ru/talk/showthread.php?s=&threadid=65869&highlight=%EF%EE%E8%F1%EA+%EF%E0%F0%E0%EC%E5%F2%F0%2A

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

Объясню на пальцах

1. Реляционная БД - в самом названии заложена суть - "реляция" есть "отношение". Т.е. не просто хранить сущьности, а хранить еще и "связи" между ними.
2. Связи реализуются с помощью так называемых "ключей".
3. Применительно к твоей задаче можно выделить следующие сущьности

- персонаж
- класс персонажа (определяет набор его свойств)
- свойство (определяет название свойства и диапазон его значений - если нужно)
- свойства класса - список свойств для каждого класса (типа шаблон персонажа)
- значения свойств персонажа - список свойств для каждого персонажа

приведем пример структуры:

1. персонаж: персонаж_ID, имя, класс_ID
2. классы: класс_ID, название_класса
3. свойство: свойство_ID, название, тип
4. свойства класса: класс_ID, свойство_ID
5. свойства персонажа: персонаж_ID, свойство_ID, значение

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

Falc

Новичок
Lord Max

Итак:
1-я нормальная форма гласит о том что все поля таблицы должны быть атомарными, следовательно записей вроде "Эндора,Шатл,n2,0,11" в одном поле быть не должно. Следовательно разновим все по разным полям. Но 2 или 3-я (сейчас уже не помню) нормальная форма гласит о том что все атрибуты сущьности должны зависить только от первичного ключа и только от него, а тут мы видим зависимость от других полей (от поля Эндора), следовательно атрибуты предметов надо выносить в отдельную таблицу. У нас уже поучилось 2 таблицы: пользователи и их предметы, находящиеся в обычном отношнии 1 ко многим. С другими атрибутами я пологаю можно поступить анологичным образом.
 

alexhemp

Новичок
Falc

Ну вот я примерно это и хотел сказать... я лично стараюсь нормализовать все до победного конца и не боюсь писать сложные запросы и оптимизировать их.
Это гораздо интереснее чем писать запрос на запись в 100 полей - такой запрос совсем не сложный, но ужасно нудный :)
И как показывает практика следовать теории крайне полезно.
 

Falc

Новичок
alexhemp
>>я лично стараюсь нормализовать все до победного конца и не боюсь писать сложные запросы и оптимизировать их.

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

Lord Max

Guest
to alexhemp
сложно разложить всё по - полочкам, без дополнительной помощи не обойтись:
Я ещё раз внимательно перечитал тему по ссылке, я понимаю систему работы товаров, там любой предмет может принадлежать любой категории, а так же может иметь произвольное количество параметров, также и параметров может быть сколько угодно много... Насколько я понимаю этот метод хорош, когда у нас есть огромное количество разноплановых товаров с разными свойствами и каждый из них может принадлежать n-й категории. Но я опять повторюсь, у меня все товары (персонажи) однотипны, у них одинаковое количество свойств (параметров) с разными значениями. Я изучил предложенный Вами вариант и даже нарисовал наглядную модель в фотошопе со всеми стрелками отношений. И получается, что при моей задаче + Ваша схема мы имеем = в таблице персонажи – списки персонажей, каждому из них соответствует только 1! Класс из таблицы классы и у этого класса есть фиксированный набор свойств и у каждого пользователя получается тоже будет по определённому количеству свойств. Вопрос : может я не правильно понял Вашу схему или Вы немного не поняли мою задачу ? Пожалуйста, не огорчайтесь, если я не правильно понимаю ход Ваших мыслей, но я ОЧЕНЬ хочу разобраться.

PS Если взять во внимание то, что у каждого пользователя может быть фиксировано 100! свойств, то у меня будет по 100 записей (в таблице свойства персонажа) на каждого пользователя таблицы пользователей.

SelenIT
Пушка - Пистолет 9мм.weapon.40.40.35.0.пусто.-.NA.-.пусто.-.NA.-.пусто.-.9mm
Строка - пусто.-.NA.-.пусто.-.NA.-.пусто.-
Там где «пусто» - можно вставить аксессуары (оптику глушитель и тд) где «NA» - нельзя , в «-» при вставке аксессуара вставляется время жизни уникального экземпляра аксессуара. Аксессуаров всего 5, соответственно всего 5 полей где варианты «пусто» и «NA» + 5 полей времени жизни.
Пример :
Пистолет 9мм.weapon.40.40.35.0.Глушитель.20.NA.-.пусто.-.NA.-.пусто.-.9mm
А дальнобойность оружия хранится тоже в этой строке («35»), так как у каждого экземпляра пушки может быть уникальная (тюнингованная дальность, урон, точность стрельбы).
PS А преобразований особых и не требуется : разбить строку Сплитом и делать с массивом всё, что требуется.

Falc
но ведь у меня и так все поля (свойства) в таблице зависят от ключа id, включая и поле "Ship" в котором записи типа "Эндора,Шатл,n2,0,11" и такое поле может быть только 1 для каждого пользователя, а в нём эта строка или null
 

Falc

Новичок
Lord Max
>>но ведь у меня и так все поля (свойства) в таблице зависят от ключа id

Да пока у тебя в полях не атомарные значения, как только ты приведешь в первую нормальную форму такого уже не будет.
 

Lord Max

Guest
to Falc
Отлично, я осознал необходимость переноса всех полей с множественными значениями в отдельные таблицы, но останется примерно 40 полей – свойств персонажа, привязанных к id и каждое поле атомарно, - это же нормализовать не обязательно ???
Кстати говоря, я наконец-то вьехал в схему связей 1 - м (персонаж - вещи\корабли) но только до сих пор не пойму как такую же систему организовать на однотипные свойства персонажа (и нужно ли?)

-~{}~ 28.11.05 23:36:

Никто больше не поделится соображениями ? ))

-~{}~ 29.11.05 17:59:

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