<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Alex Volkov</title>
	
	<link>http://alexvolkov.ru</link>
	<description>cat /var/log/life.log | grep -E "life|work|etc"</description>
	<lastBuildDate>Wed, 22 Feb 2012 17:00:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/AlexVolkov" /><feedburner:info uri="alexvolkov" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Профилирование и отладка PHP скриптов</title>
		<link>http://feedproxy.google.com/~r/AlexVolkov/~3/aOpKJb-P8Mk/php-debugging-and-profiling.html</link>
		<comments>http://alexvolkov.ru/php-debugging-and-profiling.html#comments</comments>
		<pubDate>Thu, 09 Feb 2012 14:28:19 +0000</pubDate>
		<dc:creator>Alex Volkov</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Скрипты]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[profiling]]></category>
		<category><![CDATA[xdebug]]></category>

		<guid isPermaLink="false">http://alexvolkov.ru/?p=1998</guid>
		<description><![CDATA[Отладка скриптов вообще дело крайне нужное и полезное. Кроме основной задачи &#8212; поиска и удаления ошибок, отладка прямо улучшает качество и работоспособность программы в целом. Выловленные баги, исправленная логика &#8212; все это делает программу стабильнее в работе, что весьма желанная цель при ее написании. Все ниженаписанное основывается на моем опыте, так что воспринимайте это как [...]]]></description>
			<content:encoded><![CDATA[<p>Отладка скриптов вообще дело крайне нужное и полезное. Кроме основной задачи &#8212; поиска и удаления ошибок, отладка прямо улучшает качество и работоспособность программы в целом. Выловленные баги, исправленная логика &#8212; все это делает программу стабильнее в работе, что весьма желанная цель при ее написании. Все ниженаписанное основывается на моем опыте, так что воспринимайте это как мое имхо ))</p>
<p><em>Если жмакнуть одну из этих кнопочек, то увидеть скрытый контент!</em></p>
<p><a href="http://twitter.com/share"  class="twitter-share-button" data-counturl="http://alexvolkov.ru/php-debugging-and-profiling.html"  data-url="http://alexvolkov.ru/php-debugging-and-profiling.html"  data-count="horizontal" >Tweet</a> <span style="display:inline-block; width:100px;"></span> <g:plusone callback="display_like_content" href="http://alexvolkov.ru/php-debugging-and-profiling.html"></g:plusone><div id='google_after_like' style='display:none;clear:both;width:100%;;'>Тут особо ничего интересного нет, я просто хотел потестить один плуг для вп, который обещает huge traffic waves.

Так что сорри за облом ожиданий и спасибо кнопку! :))</div><span id="more-1998"></span></p>
<p>Итак, какие бывают ошибки и как их можно отловить.</p>
<p>1. Самые простые и самые распространённые &#8212; это ошибки, связанные с чудным свойством php &#8212; динамической типизацией. Помимо того, что иногда просто упускаешь из виду, что там и в каком формате у тебя хранится, php сам подкидывает сюрпризы вида true при сравнении &#171;qwerty&#187; == 0 и другие чудеса автоматического приведения типов и подобные им брейнфаки.</p>
<p>Если точно известно место, где переменная перестает себя вести, как от нее ожидают, то я особо не мудрствую и ставлю var_dump(переменная). Если догадка подтверждается, то исправляем косяк и идем дальше.</p>
<p>Но не всегда получается определить точное место расхождения значения с ожидаемым. Расхождение это может быть зарыто глубоко в дебри кода, либо наоборот, находится на самом видном месте.</p>
<p>Так же бывает, что переменная меняет значение из-за нарушенной логики приложения. Например, присвоение идет внутри локальной видимости вложенной функции или неверно построенного цикла. Наружу передается не тот результат, который ждешь, хотя с виду все правильно. Просто не там открыл или закрыл скобку и все изменяется причудливым образом.</p>
<p>Такую красоту довольно трудно отловить руками, особенно в крупных приложениях. Поэтому лучше воспользоваться дебаггером. Во всяких умных книжках довольно часто пишут про <a href="http://pecl.php.net/package/apd">APD</a>, хвалят его, но дата его последнего релиза за 2004 год как-то меня настораживает. В багтрекере пишут, что под 5.3 не хочет он работать, у меня из груши не встал, поэтому я забил на него.</p>
<p>Трассировку скрипта можно сделать xdebug&#8217;ом. Он часто бывает установлен, но как модуль PHP, а для нормальной работы нужно, чтобы он стоял как Zend module.  По установке все итак расписано в нете, не буду повторяться.</p>
<p>Xdebug генерирует отчет, который показвает последовательно, кто, куда, зачем обратился. Есть специальные парсилки логов, но мне удобнее читать сырые отчеты, потому как в консоли особо красоту не получишь, а через веб я не умею отлаживать. Выдается вот такая красота:</p>
<pre class="brush:plain">3	67	0	0.013521	394468	drXdebugTraceFileParser-&gt;parseLine	1		/home/alex/tmp/trace.php	123	1	$line = '2\t3\t1\t0.000772\t328656\n'
4	68	0	0.013588	394584	explode	0		/home/alex/tmp/trace.php	149	2	'\t'	'2\t3\t1\t0.000772\t328656\n'
4	68	1	0.013630	395376
4	69	0	0.013666	395348	count	0		/home/alex/tmp/trace.php	150	1	array (0 =&gt; '2', 1 =&gt; '3', 2 =&gt; '1', 3 =&gt; '0.000772', 4 =&gt; '328656\n')
4	69	1	0.013716	395348
4	70	0	0.013757	395436	array_pop	0		/home/alex/tmp/trace.php	178	1	array (0 =&gt; '{main}', 1 =&gt; 'ini_set')
4	70	1	0.013800	395408
4	71	0	0.013823	395332	drXdebugTraceFileParser-&gt;addToFunction	1		/home/alex/tmp/trace.php	180	5	$function = 'ini_set'	$time = 4.3E-5	$memory = 236	$nestedTime = 0	$nestedMemory = 0
5	72	0	0.013900	395376	in_array	0		/home/alex/tmp/trace.php	194</pre>
<p>&nbsp;</p>
<p>Этого достаточно, чтобы проследить логику хода выполнения и отследить косяки. Забыл еще сказать, что xdebug можно подключать на лету. Обычно я выключаю и дебаггер и профайлер в php.ini, а в нужном скрипте просто включаю их вместе или по очереди через</p>
<pre class="brush:php">ini_set('xdebug.default_enable', 1);
ini_set('xdebug.profiler_enable', 1);</pre>
<p>Это быстро, не нужно никаких дополнительных телодвижений. Xdebug еще можно подключать на кучу разных IDE, даже вроде в денвере он есть.Таким нехитрым образом можно отловить большинство ошибок и невнимательностей в коде. Естественно, что изначально задуманную кривую логику так не исправить.</p>
<p>2. Второй тип ошибок гораздо сложнее отловить. Они также появляются вследствии зевков и невнимательностей, но проявляют себя не сразу, а по наступлению определенных условий. Например, время работы или количество итераций или появление определенного числа в арифметических операциях или наоборот, его непоявление.Еще ошибки могут возникать из-за изменений среды окружения, например форк апача завершил свою сессию и скинул скрипт или крон запускает что-то, что отъело всю память и скрипт просто не может запуститься.</p>
<p>Таких условий может быть множество, всех их обьеденяет одна черта &#8212; они не проявляются сразу при запуске, поэтому при анализе лога дебаггера ничего подозрительного выявить нельзя.</p>
<p>Тут приходит на помощь замечательная утилита &#8212; strace. Я одно время мучился с тем, что апач раз в 24 часа убивал свои потоки, а с ними и скрипты, из-под которых они были запущены. Так вот был настроен сервер. Нашли ошибку, когда подключились с другого терминала непосредственно к скрипту и слушали его через strace. Там и увидели, что скрипт ловит SIGTERM. <a href="http://alexvolkov.ru/examples-of-using-strace-to-debug-scripts.html">Как использовать strace</a> я уже писал. Позволяет исследовать реальную работу скрипта в реальном времени и видит все, что с ним происходит. Вывод можно перенаправить в файл и потом проанализировать. Еще есть схожая утилита, называет ptrace. Все они родные для nix систем. <a href="http://habrahabr.ru/blogs/php/129982/">Некоторые чуваки с хабры</a> используют для схожих целей сишный дебаггер. Кому в чем удобней&#8230;</p>
<p>3. Третий тип ошибок заключается в том, что память начинает резко утекать куда-то и нужно выяснить куда. Они также возникают из-за невнимательности или усталости и получаются чудеса типа файл инклюдится в бесконечном цикле или переменная набирает и набирает обьемиз-за того, что ее не обнулили предварительно.  Все это конечно можно отловить и через strace, но лучше использовать для этого профайлер xdebug&#8217;а.</p>
<p>Также этот способ следует использовать в целях профилактики, чтобы держать под контролем количество вызовов, открытий файлов и размеров переменных. Сам xdebug конечно не отдает все в удобноваримом виде, но под чтение его отчетов есть куча утилит. Я пользуюсь<a href="http://derickrethans.nl/xdebug-and-tracing-memory-usage.html"> этим скриптом</a>. Он выдает отчеты вида</p>
<pre class="brush:plain">function            #calls time memory time memory
------------------------------------------------------------
ini_set                  3 0.0002      584 0.0002      584
fix_string               1 0.0010      264 0.0009      184
xdebug_call_file         1 0.0001       48 0.0001       48
xdebug_call_function     1 0.0000       32 0.0000       32
var_dump                 1 0.0002        0 0.0002        0
xdebug_memory_usage      1 0.0000        0 0.0000        0
xdebug_call_line         1 0.0000        0 0.0000        0
{main}                   1 0.0018      480 0.0003     -368</pre>
<p>Здесь уже можно отследить и вызовы  и время. Запускаю его обычно в конце работы, чтобы посмотреть, не напортачил ли я чего в коде. Также использую его при оптимизации для оценки результатов</p>
<p>Вот такие нехитрые способы, надеюсь, помогут спасти время и нервы при отладке скриптов. Если есть у кого свои методики &#8212; велкам в коменты, буду рад услышать.</p>
<p>P.S. Если кто знает, как завести APD под 5.3, отпишитесь плз!</p>
<p>P.P.S <a href="https://www.progclub.org/blog/2012/01/10/profiling-a-php-script/">Тут вот чувак просто тру-самурай</a>, целый квест прошел чтобы найти ошибку. Шрифт жесть.</p>
<p>Там строку 967 в файле php_apd.c надо закоментить и все заработает.</p>
<p>И чтобы сделать читалку логов, надо скомпиленную pprofp скопировать в /usr/bin и создать ссылку на php в /usr/local/bin/</p>
<h2  class="related_post_title">На закуску.</h2><ul class="related_post"><li><a href="http://alexvolkov.ru/problems-with-the-serialization-of-arrays.html" title="Проблемы с сериализацией массивов">Проблемы с сериализацией массивов</a></li><li><a href="http://alexvolkov.ru/class-to-work-with-the-service-reduction-options.html" title="Класс для работы с сервисами сокращения ссылок">Класс для работы с сервисами сокращения ссылок</a></li><li><a href="http://alexvolkov.ru/a-simple-way-to-test-the-process-on-the-existence-of.html" title="Простой способ проверки процесса на существование">Простой способ проверки процесса на существование</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://alexvolkov.ru/php-debugging-and-profiling.html/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		<feedburner:origLink>http://alexvolkov.ru/php-debugging-and-profiling.html</feedburner:origLink></item>
		<item>
		<title>Денормализация базы данных</title>
		<link>http://feedproxy.google.com/~r/AlexVolkov/~3/OtD-rhsROJ8/database-denormalization.html</link>
		<comments>http://alexvolkov.ru/database-denormalization.html#comments</comments>
		<pubDate>Thu, 22 Dec 2011 14:21:49 +0000</pubDate>
		<dc:creator>Alex Volkov</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[Теория]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[normalization]]></category>

		<guid isPermaLink="false">http://alexvolkov.ru/?p=1991</guid>
		<description><![CDATA[Не так давно писал цикл постов про нормальные формы. Сегодня хочу еще рассказать про обратную процедуру &#8212; денормализацию. Что такое денормализация? Это намеренное внесение изменений в нормализованную схему бд, после которых она перестает соответствовать правилам НФ. Для чего это делается? Основная цель &#8212; это увеличение производительности ценой увеличения избыточности, возможных коллизий, а также некоторым неудобством [...]]]></description>
			<content:encoded><![CDATA[<p>Не так давно писал цикл постов про <a title="Нормализация баз данных" href="http://alexvolkov.ru/database-normalizatio.html">нормальные формы</a>. Сегодня хочу еще рассказать про обратную процедуру &#8212; денормализацию.</p>
<p><strong>Что такое денормализация</strong>? Это намеренное внесение изменений в нормализованную схему бд, после которых она перестает соответствовать правилам НФ.</p>
<p><strong> Для чего это делается?</strong> Основная цель &#8212; это увеличение производительности ценой увеличения избыточности, возможных коллизий, а также некоторым неудобством составления сложных выборок.  <span id="more-1991"></span></p>
<p>Когда то давно я делал глупые сравнения &#8212; <a href="http://alexvolkov.ru/bd-bystree-fajjlov.html">быстродействие бд и файлов </a>на предмет чтения из них. Вся прелесть баз в том, что можно задать целую кучу критериев для выборки, чего в файлах сделать нереально. Естественно, база уступит в простом чтении файлу.</p>
<p>Но иногда базы имеют настолько сложную структуру, что при выполнении выборки перелопачиваются сотни тысяч строк кода и это сказывается на быстродействии. И если схема нормализованна, то запрос будет идти уже не к одной таблице, а ко многим (в зависимости от числа сущностей). Что в свою очередь, увеличит время выполнения запроса еще в N раз.</p>
<p>Вот в таких случаях идет под нож структура бд и все данные намерянно помещаются в меньшее число таблиц. Чаще всего так делают, когда к базе идут, в основном, запросы на чтение. Таким образом уменьшается число соединений между таблицами.</p>
<h2  class="related_post_title">На закуску.</h2><ul class="related_post"><li><a href="http://alexvolkov.ru/database-normalization-third-normal-form.html" title="Нормализация баз данных: третья нормальная форма">Нормализация баз данных: третья нормальная форма</a></li><li><a href="http://alexvolkov.ru/database-normalization-second-normal-form.html" title="Нормализация баз данных: вторая нормальная форма">Нормализация баз данных: вторая нормальная форма</a></li><li><a href="http://alexvolkov.ru/normalization-of-databases-first-normal-form.html" title="Нормализация баз данных: первая нормальная форма">Нормализация баз данных: первая нормальная форма</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://alexvolkov.ru/database-denormalization.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://alexvolkov.ru/database-denormalization.html</feedburner:origLink></item>
		<item>
		<title>Дизайн интерфейсов онлайн</title>
		<link>http://feedproxy.google.com/~r/AlexVolkov/~3/7ipaXWaOh-4/designing-interface-online.html</link>
		<comments>http://alexvolkov.ru/designing-interface-online.html#comments</comments>
		<pubDate>Tue, 20 Dec 2011 12:15:53 +0000</pubDate>
		<dc:creator>Alex Volkov</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[дизайн]]></category>
		<category><![CDATA[интерфейс]]></category>
		<category><![CDATA[онлайн]]></category>

		<guid isPermaLink="false">http://alexvolkov.ru/?p=1878</guid>
		<description><![CDATA[Много раз бывает такая ситуация, когда нужно обговорить, как будет выглядеть будущий элемент дизайна, но через аську или скайп рассказывать что вот тут разместится вот это а там вон то совсем не айс. Гораздо удобнее накидать в редакторе наброски, отправить и согласовать их. Но только каждый раз что-то править, потом сохранять, потом отправлять совсем не [...]]]></description>
			<content:encoded><![CDATA[<p>Много раз бывает такая ситуация, когда нужно обговорить, как будет выглядеть будущий элемент дизайна, но через аську или скайп рассказывать что вот тут разместится вот это а там вон то совсем не айс. Гораздо удобнее накидать в редакторе наброски, отправить и согласовать их. Но только каждый раз что-то править, потом сохранять, потом отправлять совсем не удобно.<br />
Есть такие сервисы, которые предоставляют возможность сделать тоже самое, но только совместно и онлайн.</p>
<p>Большинство из таких сервисов предоставяют бесплатный пробный доступ на несколько дней, но я искал полностью бесплатный вариант, пускай и не сильно функциональный.<br />
<span id="more-1878"></span></p>
<h3><a href="http://lumzy.com/">Lumzy</a></h3>
<p>Дают только 15 дней триала. Немного детский интерфейс, есть ночной вариант дизайна. Попробовал накидать форму, не смог поменять текст в текстовом поле. На том и закрыл его, не совсем он интуитивен.</p>
<p><a href="http://alexvolkov.ru/wp-content/uploads/2011/12/lumzy.png"><img class="alignnone size-medium wp-image-1979" title="lumzy" src="http://alexvolkov.ru/wp-content/uploads/2011/12/lumzy-300x214.png" alt="" width="300" height="214" /></a><br/><br/><br/></p>
<h3><a href="https://gomockingbird.com/">Mockingbird</a></h3>
<p>Крайне серьёзный онлайн-редактор с дизайном в стиле мака. Есть возможность сохранять, приглашать друзей для совместной работы. И просто отличный интерфейс, все понятно, все находится само собой. За 20 минут набросал концепт, впечатления от работы крайне положительные. Бесплатная версия дает 1 проект и 10 страниц. Для небольшой работы вместе вполне пригодится.<br />
<a href="http://alexvolkov.ru/wp-content/uploads/2011/12/mockingbird.png"><img class="alignnone size-medium wp-image-1980" title="mockingbird" src="http://alexvolkov.ru/wp-content/uploads/2011/12/mockingbird-300x214.png" alt="" width="300" height="214" /></a><br/><br/><br/></p>
<h3><a href="http://mockflow.com/">MockFlow</a></h3>
<p>Еще один весьма неплохой редактор. Есть возможность импорта-экспорта, расшаривания. Весьма широкие наборы компоненты. И одна супер фича &#8212; есть пользовательская библиотека готовых шаблонов. Можно выбрать уже созданные кем-то шаблоны и заюзать их для своих целей. Есть ревизии для проектов. В халявной версии 4 страницы, 10 мегабайт хранилица и двое сотрудников для одновременного труда. Экспорт с водной маркой сервиса.Конкурент mockingbird.</p>
<p><a href="http://alexvolkov.ru/wp-content/uploads/2011/12/mockflow.png"><img class="alignnone size-medium wp-image-1981" title="mockflow" src="http://alexvolkov.ru/wp-content/uploads/2011/12/mockflow-300x214.png" alt="" width="300" height="214" /></a><br/></p>
<h2  class="related_post_title">На закуску.</h2><ul class="related_post"><li>Ничего нет похожего на этот пост, он неповторим</li></ul>]]></content:encoded>
			<wfw:commentRss>http://alexvolkov.ru/designing-interface-online.html/feed</wfw:commentRss>
		<slash:comments>15</slash:comments>
		<feedburner:origLink>http://alexvolkov.ru/designing-interface-online.html</feedburner:origLink></item>
		<item>
		<title>Нормализация баз данных: третья нормальная форма</title>
		<link>http://feedproxy.google.com/~r/AlexVolkov/~3/_ItBz0XPQFw/database-normalization-third-normal-form.html</link>
		<comments>http://alexvolkov.ru/database-normalization-third-normal-form.html#comments</comments>
		<pubDate>Tue, 15 Nov 2011 17:45:37 +0000</pubDate>
		<dc:creator>Alex Volkov</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[Теория]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[normalization]]></category>

		<guid isPermaLink="false">http://alexvolkov.ru/?p=1972</guid>
		<description><![CDATA[Последний пост про нормальные формы, перевод книги PHP 6 and MySQL 5 for Dynamic Web Sites. Предыдущие три вынесены ссылками в конце поста. Третья нормальная форма. База данных будет находиться в третьей нормальной форме, если она приведена ко второй нормальной форме и каждый не ключевой столбец независим друг от друга. Если следовать процессу нормализации правильно [...]]]></description>
			<content:encoded><![CDATA[<p>Последний пост про нормальные формы, перевод книги <a title="PHP 6 and MySQL 5 for Dynamic Web Sites" href="http://goo.gl/x9mdy">PHP 6 and MySQL 5 for Dynamic Web Sites</a>. Предыдущие три вынесены ссылками в конце поста.<span id="more-1972"></span></p>
<h2>Третья нормальная форма.</h2>
<p><img class="alignnone" title="вторая нормальная форма" src="http://alexvolkov.ru/wp-content/uploads/2011/11/2nf-compatible.png" alt="" width="426" height="348" /></p>
<p>База данных будет находиться в третьей нормальной форме, если она приведена ко второй нормальной форме и каждый не ключевой столбец независим друг от друга. Если следовать процессу нормализации правильно до этой точки, с приведением к 3НФ может и не возникнуть вопросов. Следует знать, что 3НФ нарушается,  если изменив значение в одном столбце, потребуется изменение и в другом столбце.  В примере с форумом (рисунок вверху), проблем с приведением к 3НФ не возникнет, но можно рассмотреть как образец гипотетическую ситуацию, где это может произойти.</p>
<p>Возьмём, как образец, одиночную таблицу, которая хранит некую информацию о бизнес клиентах: имя, фамилию, телефон, адрес, город, штат, почтовый индекс и все в этом духе.  Такая таблица не будет находится в 3НФ, поскольку тут много полей будет взаимозависимо &#8212; улица будет зависеть от города, город от штата, почтовый индекс тоже под вопросом. Все эти поля будут подчинены друг другу, а не человеку, к которому относится эта запись.</p>
<p>Чтобы нормализовать такую базу, нужно создать по таблице для штатов, городов (с внешним ключом, ведущим в таблицу штатов) и для почтовых кодов. Все они будут ссылаться назад на клиентскую таблицу.</p>
<p>Если вы чувствуете, что все эти действия могут быть излишними, вы правы.  Честно, в верхних уровнях нормализации часто нет необходимости.  Смысл в том, что нужно стараться нормализовать базу данных, но иногда приходиться идти на уступки ради того, чтобы не допустить чрезмерного усложнения. Потребности приложения и структура данных в базе подскажут, насколько потребуется проводить процесс нормализации.</p>
<p>Как уже говорилось,  пример с форумом уже достаточно нормализован, но все равно опишем шаги для нормализации для третьей нормальной формы, показав как исправить пример с клиентами.</p>
<h2>Чтобы привести базу к третьей нормальной форме, надо:</h2>
<p>1. Определить, в каких полях каких таблиц имеется взаимозависимость. Как только что говорилось, поля, которые зависят больше друг от друга (как город от штата), чем от ряда в целом. В базе форума такой проблемы нет. Взглянув на таблицу сообщений, увидите, что каждый заголовок, каждое тело сообщения относится к своему message ID.</p>
<p>2. Создайте соответствующие таблицы. Если есть проблемный столбец в шаге 1, создавайте раздельные таблицы для него. Как города и штаты, в примере с клиентами.</p>
<p>3. Создайте или выделите первичные ключи. Каждая таблица должна иметь первичный ключ. Для примера с клиентами это будут city ID и state ID.</p>
<p>4. Создайте необходимые внешние ключи, которые образуют любое из отношений. В нашем примере нужно добавить state ID в таблицу городов и city ID в таблицу клиентов. Это свяжет каждого клиента с городом и штатом, где они живут.</p>
<div id="attachment_1973" class="wp-caption alignnone" style="width: 430px"><a href="http://alexvolkov.ru/wp-content/uploads/2011/11/3nf.png"><img class="size-full wp-image-1973" title="third normal form example" src="http://alexvolkov.ru/wp-content/uploads/2011/11/3nf.png" alt="" width="420" height="294" /></a><p class="wp-caption-text">Рассмотренная в качестве примера база данных с записями о клиентах, созданы две новых таблицы для хранения информации о городах и штатах.</p></div>
<h3>Подсказки:</h3>
<p>Вообще, можно было бы и не нормализовывать базу с клиентами до такой степени. Если оставить города и штаты в таблице клиентов, самое страшное, что могло бы случиться &#8212; если бы город изменил название, нужно было бы менять его во всех записях о клиентах, которые живут в этом городе. Но города редко меняют свои имена.</p>
<p>Несмотря на то, что имеются правила как нормализовывать базы данных, разные люди сделают это разными способами.  Проектирование баз данных допускает личные предпочтения и интерпретации. Важно, чтобы в базе не было явных нарушений нормальных форм, которые могут привести в дальнейшем к проблемам.</p>
<h2>Нарушения правил нормализации</h2>
<p>Убедившись, что база данных в 3НФ поможет гарантировать надёжность и жизнеспособность, не нужно полностью нормализовывать все базу, с которыми вы работаете. Перед тем, как использовать эти методы, имейте ввиду, что это может иметь долгосрочные разрушающие последствия.</p>
<p>Две основных причины, чтобы нарушить правила нормализации &#8212; удобство и быстродействие. Меньшим число таблиц проще управлять, чем большим. Кроме того, из-за более сложного характера, нормализованные таблицы более медленные для обновления, изменения и выдачи данных. Вкратце, нормализация это сделка между целостностью/расширяемостью и простотой/скоростью. С другой стороны, есть достаточно способов чтобы улучшить производительность базы данных, но не так много способов чтобы исправить повреждённые данные, возникшие из-за плохого дизайна структуры.</p>
<p>Практика и опыт подскажут, как сделать модель базы данных, но лучше совершайте ошибки пробуя нормальные формы, хотя бы до тех пор, пока не поймете принцип.</p>
<h3>Ссылки:</h3>
<ol>
<li><a title="Нормализация баз данных" href="http://alexvolkov.ru/database-normalizatio.html">Введение</a></li>
<li><a title="Первая нормальная форма" href="http://alexvolkov.ru/normalization-of-databases-first-normal-form.html">Первая нормальная форма</a></li>
<li><a title="Вторая нормальная форма" href="http://alexvolkov.ru/database-normalization-second-normal-form.html">Вторая нормальная форма</a></li>
<li><a href="http://ru.wikipedia.org/wiki/%D0%9D%D0%BE%D1%80%D0%BC%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%B1%D0%B0%D0%B7_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85">Вики о нормализации</a></li>
<li><a href="http://www.mysql.com/downloads/workbench/">Mysql Workbench</a> &#8212; программа для проектирования баз данных</li>
</ol>
<h2  class="related_post_title">На закуску.</h2><ul class="related_post"><li><a href="http://alexvolkov.ru/database-denormalization.html" title="Денормализация базы данных">Денормализация базы данных</a></li><li><a href="http://alexvolkov.ru/database-normalization-second-normal-form.html" title="Нормализация баз данных: вторая нормальная форма">Нормализация баз данных: вторая нормальная форма</a></li><li><a href="http://alexvolkov.ru/normalization-of-databases-first-normal-form.html" title="Нормализация баз данных: первая нормальная форма">Нормализация баз данных: первая нормальная форма</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://alexvolkov.ru/database-normalization-third-normal-form.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://alexvolkov.ru/database-normalization-third-normal-form.html</feedburner:origLink></item>
		<item>
		<title>Нормализация баз данных: вторая нормальная форма</title>
		<link>http://feedproxy.google.com/~r/AlexVolkov/~3/3RdO5_2B2lo/database-normalization-second-normal-form.html</link>
		<comments>http://alexvolkov.ru/database-normalization-second-normal-form.html#comments</comments>
		<pubDate>Mon, 14 Nov 2011 10:36:12 +0000</pubDate>
		<dc:creator>Alex Volkov</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[Теория]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[normalization]]></category>

		<guid isPermaLink="false">http://alexvolkov.ru/?p=1962</guid>
		<description><![CDATA[Третий пост, перевод книги PHP 6 and MySQL 5 for Dynamic Web Sites. Предыдущие два:  вводный, 1НФ Вторая нормальная форма. Для приведения таблиц ко второй нормальной форме (2НФ), приводимые таблицы должны быть уже в 1НФ. Нормализация должна проходить по порядку. Теперь, во второй нормальной форме, должно быть соблюдено условие &#8212; любой столбец, который не является [...]]]></description>
			<content:encoded><![CDATA[<p>Третий пост, перевод книги <a title="PHP 6 and MySQL 5 for Dynamic Web Sites" href="http://goo.gl/x9mdy">PHP 6 and MySQL 5 for Dynamic Web Sites</a>. Предыдущие два:  <a href="http://alexvolkov.ru/database-normalizatio.html">вводный</a>, <a href="http://alexvolkov.ru/normalization-of-databases-first-normal-form.html">1НФ</a><span id="more-1962"></span></p>
<h2>Вторая нормальная форма.</h2>
<p>Для приведения таблиц ко второй нормальной форме (2НФ), приводимые таблицы должны быть уже в 1НФ. Нормализация должна проходить по порядку.</p>
<p>Теперь, во второй нормальной форме, должно быть соблюдено условие &#8212; любой столбец, который не является ключом (в том числе внешним), должен зависеть от первичного ключа. Обычно такие столбцы, имеющие значения, который не зависят от ключа, легко определить. Если данные, содержащиеся в столбце, не имеют отношения к ключу, который описывает строку, то их следует отделять в свою отдельную таблицу. В старую таблицу надо возвращать первичный ключ.</p>
<p><img class="alignnone" title="second normal form violation" src="http://alexvolkov.ru/wp-content/uploads/2011/11/5a.png" alt="" width="415" height="219" /></p>
<p>На рисунке выше и названия фильмов и имена актеров нарушают правила 2НФ (сами не являются ключами и не зависят от первичного ключа).</p>
<p>После всех преобразований, база данных с фильмами будет иметь минимум 4 таблицы.</p>
<div id="attachment_1963" class="wp-caption alignnone" style="width: 436px"><a href="http://alexvolkov.ru/wp-content/uploads/2011/11/2nf-fail.png"><img class="size-full wp-image-1963" title="2НФ конечная версия" src="http://alexvolkov.ru/wp-content/uploads/2011/11/2nf-fail.png" alt="" width="426" height="212" /></a><p class="wp-caption-text">Чтобы привести бд ко второй нормальной форме, потребовалось 4 таблицы. Режиссёры (directors), представлены в фильмах (movies) через внешний ключ director ID, фильмы в таблице фильмы-актёры (movies-actors) через movie ID, актеры через actor ID</p></div>
<p>Каждое имя режиссёра, название картины и имя актера хранится только один раз и все неключевые поля зависят от первичного ключа их собственной таблицы.</p>
<p>По факту, нормализация может быть утрированно названа процессом создания все новых и новых таблиц до тех пор, пока избыточность и повторения не будут полностью уничтожены.</p>
<h3>Чтобы привести базу ко второй нормальной форме, надо:</h3>
<div id="attachment_1965" class="wp-caption alignnone" style="width: 447px"><a href="http://alexvolkov.ru/wp-content/uploads/2011/11/2nf-example.png"><img class="size-full wp-image-1965" title="2nf-example" src="http://alexvolkov.ru/wp-content/uploads/2011/11/2nf-example.png" alt="" width="437" height="298" /></a><p class="wp-caption-text">Чтобы привести эту базу к 2НФ, нужно 3 таблицы минимум</p></div>
<ul>
<li>Определить все столбцы, которые не находятся в прямой зависимости от первичного ключа этой таблицы. На рисунке выше у таблиц users и forums нет первичного ключа. У таблицы messages первичный ключ &#8212; message ID, от которого зависят все остальные поля этой таблицы.</li>
<li>Создаем необходимые поля в таблицах users и forums, выделяем из существующих полей или создаем из новых первичные ключи.
<p><div id="attachment_1966" class="wp-caption alignnone" style="width: 444px"><a href="http://alexvolkov.ru/wp-content/uploads/2011/11/2nf-example-a.png"><img class="size-full wp-image-1966" title="2nf-example-a" src="http://alexvolkov.ru/wp-content/uploads/2011/11/2nf-example-a.png" alt="" width="434" height="352" /></a><p class="wp-caption-text">Для каждой таблицы нужен свой первичный ключ</p></div></li>
<li>Создаем внешние ключи и обозначаем их отношения между таблицами. Конечным шагом нормализации до 2НФ будет являться выделение внешних ключей для связи с ассоциированными таблицами. Первичный ключ одной таблицы должен быть внешним ключом в другой. На рисунке снизу показана связь между ключами трех таблиц. Поле user ID таблицы messages является первичным ключом поля user ID таблицы users.  Тип связи между ними &#8212; один ко многим. Один пользователь может оставить много сообщений, но у сообщения может быть только один пользователь. Такая же связь соединяет таблицы forums и messages через forum ID. У форума может быть много сообщений, но сообщение может находиться только в одном форуме.</li>
</ul>
<div id="attachment_1968" class="wp-caption alignnone" style="width: 436px"><a href="http://alexvolkov.ru/wp-content/uploads/2011/11/2nf-compatible.png"><img class="size-full wp-image-1968" title="2nf-compatible" src="http://alexvolkov.ru/wp-content/uploads/2011/11/2nf-compatible.png" alt="" width="426" height="348" /></a><p class="wp-caption-text">Чтобы соотнести три таблицы, в messages добавлено два внешних ключа, ведущих на первичные ключи в своих таблицах</p></div>
<p>&nbsp;</p>
<h3>Подсказки:</h3>
<ul>
<li>Другой способ приведения схемы к 2НФ &#8212; посмотреть на отношения между таблицами. Идеальный вариант &#8212; создать все отношения вида один-к-многим. Отношения вида многие-к-многим нуждаются в реструктуризации.</li>
<li>Если взглянуть еще раз на таблицу movies-actors, то можно заметить, что она является промежуточной таблицей. Она превращает отношение многие-к-многим между movies и actors в один-к-многим. Можно вводить такие промежуточные таблицы, у которых все столбцы являются ключами. В таких таблицах не требуется свой собственный первичный ключ, поскольку он может быть комбинацией двух внешних ключей.</li>
<li>Нормализованная должным образом таблица никогда не будет иметь повторяющихся рядов (двух и более рядов, значения которых не являются ключами и содержат совпадающие данные).</li>
<li>Чтобы упростить нормализацию, помните, что при приведении к 1НФ вы ищете дубли горизонтально (дубли столбцов), а при приведении к 2НФ &#8212; вертикально (дубли рядов).</li>
</ul>
<h2  class="related_post_title">На закуску.</h2><ul class="related_post"><li><a href="http://alexvolkov.ru/database-denormalization.html" title="Денормализация базы данных">Денормализация базы данных</a></li><li><a href="http://alexvolkov.ru/database-normalization-third-normal-form.html" title="Нормализация баз данных: третья нормальная форма">Нормализация баз данных: третья нормальная форма</a></li><li><a href="http://alexvolkov.ru/normalization-of-databases-first-normal-form.html" title="Нормализация баз данных: первая нормальная форма">Нормализация баз данных: первая нормальная форма</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://alexvolkov.ru/database-normalization-second-normal-form.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://alexvolkov.ru/database-normalization-second-normal-form.html</feedburner:origLink></item>
		<item>
		<title>Нормализация баз данных: первая нормальная форма</title>
		<link>http://feedproxy.google.com/~r/AlexVolkov/~3/ix-vrkpbnOY/normalization-of-databases-first-normal-form.html</link>
		<comments>http://alexvolkov.ru/normalization-of-databases-first-normal-form.html#comments</comments>
		<pubDate>Fri, 11 Nov 2011 19:14:21 +0000</pubDate>
		<dc:creator>Alex Volkov</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[Теория]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[normalization]]></category>

		<guid isPermaLink="false">http://alexvolkov.ru/?p=1953</guid>
		<description><![CDATA[Итак, в предыдущем посте была вводная часть про нормализацию баз данных, ключи и отношения. В этом посте будет рассмотрена первая нормальная форма или 1НФ сокращено. Первая нормальная форма Как писалось выше, нормализация &#8212; это приведение структуры бд в порядок в соответствии с несколькими правилами. Правилам нужно следовать точно, и приводить к формам нужно в порядке [...]]]></description>
			<content:encoded><![CDATA[<p>Итак, в предыдущем посте была вводная часть про <a href="http://alexvolkov.ru/database-normalizatio.html">нормализацию баз данных</a>, ключи и отношения. В этом посте будет рассмотрена первая нормальная форма или 1НФ сокращено.<span id="more-1953"></span></p>
<h2>Первая нормальная форма</h2>
<p>Как писалось выше, нормализация &#8212; это приведение структуры бд в порядок в соответствии с несколькими правилами. Правилам нужно следовать точно, и приводить к формам нужно в порядке их следования.</p>
<p>Чтобы привести таблицу к 1НФ, нужно соблюсти два правила:</p>
<ol>
<li>Атомарность или неделимость. Каждая колонка должна содержать одно неделимое значение.</li>
<li>Таблица не должна содержать повторяющихся колонок или групп данных.</li>
</ol>
<p>Например, если таблица содержит в одном поле полный адрес человека (улица, город, почтовый код), не будет отвечать правилам 1НФ, поскольку будет содержать различные значения в одном столбце, что будет нарушением правила об атомарности. Или если бд содержит данные о фильмах и в ней есть столбцы актер1, актер2, актер3, также не будет отвечать правилам, поскольку будет иметь место повторению данных.</p>
<p>Начинать нормализацию следует с проверки структуры бд на совместимость с 1НФ. Все столбцы, которые не являются атомарными, должны быть разбиты на составляющие их столбцы. Если в таблице есть повторяющиеся столбцы, то им нужно выделить отдельную таблицу.</p>
<p><a href="http://alexvolkov.ru/wp-content/uploads/2011/11/4.png"><img class="alignnone size-full wp-image-1954" title="атомарная таблица" src="http://alexvolkov.ru/wp-content/uploads/2011/11/4.png" alt="" width="435" height="360" /></a></p>
<h3>Чтобы привести таблицу к первой нормальной форме, следует:</h3>
<ul>
<li>Найти все поля, которые содержат многосоставные части информации. На рисунке выше, поле message date содержит день, месяц, год и время, которое можно разбить на составные части, но в данном примере такая детализация даты не нужна.  Mysql может работать и с таким форматом &#8212; благодаря типу DATETIME. В этом примере разбито имя пользователя на имя и фамилию. Еще примерами неудачных решений могут быть поля, в которых хранятся сразу все телефоны человека (мобильный, рабочий) или его интересы (готовка, танцы).</li>
<li>Те данные, которые можно разбить на составные части, нужно выносить в отдельные поля. На рисунке выше так разнесено полное имя на имя и фамилию.</li>
<li>Выносите повторяющиеся данные в отдельную таблицу. В примере с форумом такой проблемы нет, поэтому возьмем в качестве примера таблицу, содержащую информацию о фильмах. Там есть несколько полей actor, которые являются повторяемыми. Повторяемые поля тут несут две проблемы. Если хранить информацию об актерах таким образом, то их число будет лимитировано числом таблиц. Даже если их будет 100, то все равно это будет пределом для некоторых фильмов. И вторая проблема &#8212; будет большое количество пустых(NULL) ячеек для большинства остальных записей, чего также следует избегать. Решением этой проблемы станет создание отдельной таблицы для актеров, куда будет заносится информация обо всех необходимых фильмах. Имена актеров также разбиты, чтобы соблюсти атомарность. Также в этой таблице присутствует свой первичный ключ, что является необходимым условием для нормализации.</li>
<li>Дважды проверьте, все ли таблицы подходят под условия первой нормальной формы.</li>
</ul>
<div id="attachment_1957" class="wp-caption alignnone" style="width: 430px"><a href="http://alexvolkov.ru/wp-content/uploads/2011/11/5.png"><img class="size-full wp-image-1957" title="проблема избыточных полей" src="http://alexvolkov.ru/wp-content/uploads/2011/11/5.png" alt="проблема избыточных полей" width="420" height="280" /></a><p class="wp-caption-text">проблема избыточных полей</p></div>
<div id="attachment_1956" class="wp-caption alignnone" style="width: 425px"><a href="http://alexvolkov.ru/wp-content/uploads/2011/11/5a.png"><img class="size-full wp-image-1956" title="проблема избыточных полей" src="http://alexvolkov.ru/wp-content/uploads/2011/11/5a.png" alt="проблема избыточных полей" width="415" height="219" /></a><p class="wp-caption-text">решение проблемы избыточных полей</p></div>
<p>Подсказки</p>
<ul>
<li>Простейший путь приведения к 1НФ &#8212; это пройтись глазами по всем столбцам. Проверьте каждый ряд на отсутствие повторения схожих данных и делимости.</li>
<li>Разные источники трактуют процесс нормализации по своему, в основном более сухим, техническим языком. Более важен результат нормализации, а не повторение правил и умных слов.</li>
</ul>
<p>Следующий пост будет посвящен второй нормальной форме &#8212; 2НФ.</p>
<h3>На почитать</h3>
<ul>
<li><a title="Нормализация баз данных" href="http://alexvolkov.ru/database-normalizatio.html">Мой вводный пост о нормализации</a></li>
<li>Вики о <a href="http://ru.wikipedia.org/wiki/%D0%9F%D0%B5%D1%80%D0%B2%D0%B0%D1%8F_%D0%BD%D0%BE%D1%80%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D1%84%D0%BE%D1%80%D0%BC%D0%B0">1НФ </a>Там же дано четкое определение атомарности.<a href="http://ru.wikipedia.org/wiki/%D0%9F%D0%B5%D1%80%D0%B2%D0%B0%D1%8F_%D0%BD%D0%BE%D1%80%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D1%84%D0%BE%D1%80%D0%BC%D0%B0"><br />
</a></li>
<li>Сайт <a href="http://www.mstu.edu.ru/study/materials/zelenkov/ch_4_2.html#4_2_2">Мурманского технического университета</a></li>
</ul>
<h2  class="related_post_title">На закуску.</h2><ul class="related_post"><li><a href="http://alexvolkov.ru/database-denormalization.html" title="Денормализация базы данных">Денормализация базы данных</a></li><li><a href="http://alexvolkov.ru/database-normalization-third-normal-form.html" title="Нормализация баз данных: третья нормальная форма">Нормализация баз данных: третья нормальная форма</a></li><li><a href="http://alexvolkov.ru/database-normalization-second-normal-form.html" title="Нормализация баз данных: вторая нормальная форма">Нормализация баз данных: вторая нормальная форма</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://alexvolkov.ru/normalization-of-databases-first-normal-form.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://alexvolkov.ru/normalization-of-databases-first-normal-form.html</feedburner:origLink></item>
		<item>
		<title>Нормализация базы данных</title>
		<link>http://feedproxy.google.com/~r/AlexVolkov/~3/nc_-e_pWSTA/database-normalizatio.html</link>
		<comments>http://alexvolkov.ru/database-normalizatio.html#comments</comments>
		<pubDate>Thu, 10 Nov 2011 15:52:44 +0000</pubDate>
		<dc:creator>Alex Volkov</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[Теория]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[theory]]></category>

		<guid isPermaLink="false">http://alexvolkov.ru/?p=1937</guid>
		<description><![CDATA[Попала в руки одна замечательная книжка &#8212; PHP 6 and MySQL 5 for Dynamic Web Sites , за авторством Larry Ulman. В целом, книга расчитана на новичков &#8212; середнячков, но затрагиваются и довольно серьёзные вещи, при чем объясняется весьма доходчивым языком. Задела глава про нормальные формы. Довольно мудрёную тему автор раскрывает в весьма доходчивой манере. [...]]]></description>
			<content:encoded><![CDATA[<p>Попала в руки одна замечательная книжка &#8212; <a title="PHP 6 and MySQL 5 for Dynamic Web Sites" href="http://goo.gl/x9mdy">PHP 6 and MySQL 5 for Dynamic Web Sites</a> , за авторством <strong>Larry Ulman</strong>. В целом, книга расчитана на новичков &#8212; середнячков, но затрагиваются и довольно серьёзные вещи, при чем объясняется весьма доходчивым языком.</p>
<p>Задела глава про нормальные формы. Довольно мудрёную тему автор раскрывает в весьма доходчивой манере. На русском издания я не нашел, поэтому перевел эту часть книги. Обьем статьи довольно большой, поэтому я разобью на несколько постов. В этом будет вводная часть.</p>
<p>Вкратце, что такое нормализация. Большинство современных субд разработаны на основе реляционной алгебры, которая появилась раньше самих реляционных субд под авторством некого доктора Кодда. Он же вывел несколько правил, или форм, по упорядочиванию данных и их отношений. Всего таких форм 6 + две вне конкурса, Бойса-Кодда и доменно-ключевая.</p>
<p>На практике редко нормализуют дальше 3-ей нормальной формы. Поподробнее узнать обо всех нормальных формах и теории по ссылкам внизу поста.<span id="more-1937"></span></p>
<p>Все примеры из книги показаны на бд для форума с обычной для форумов структурой &#8212; посты, авторы, время и т.п.</p>
<p>Вот так выглядит схема до преобразования.<br />
<a href="http://alexvolkov.ru/wp-content/uploads/2011/11/1.png"><img class="alignnone size-full wp-image-1939" title="сырая база данных" src="http://alexvolkov.ru/wp-content/uploads/2011/11/1.png" alt="" width="418" height="297" /></a></p>
<h2>Ключи</h2>
<p>Ключи  являются составляющей частью нормализованных таблиц. Бывают двух видов &#8212; внешние и первичные.</p>
<p>Первичный ключ &#8212; это уникальный идентификатор, отвечающий следующим условиям:</p>
<ol>
<li>Он должен иметь значение, не NULL.</li>
<li>Быть неизменным &#8212; значение ключа не должно меняться.</li>
<li>Иметь уникальное значение для каждой строки.</li>
</ol>
<p>Внешние ключи &#8212; это ссылки на первичные ключи других таблиц, которые удовлетворяют условиям выше.</p>
<p>Для начала нормализации следует указать хотя бы один первичный ключ. В примере это будет message ID.</p>
<p><a href="http://alexvolkov.ru/wp-content/uploads/2011/11/2.png"><img class="alignnone size-full wp-image-1941" title="База данных с первичным ключом" src="http://alexvolkov.ru/wp-content/uploads/2011/11/2.png" alt="" width="422" height="330" /></a></p>
<p>Для указания первичного ключа, надо найти поле, которое будет подходить под все три условия. Если такого поля нет, его надо создать. В идеале, поле должно иметь тип integer.</p>
<h2> Отношения</h2>
<p>Отношения &#8212; это указатели, которые показывают, как соотносятся данные в одной таблице с данными в другой. Проще говоря, ссылка с одного столбца первой таблицы на другой столбец второй таблицы. Бывают трех видов &#8212; один-к-одному, один-к-многим, многие-к-многим.</p>
<p>Отношение один-к-одному означает что поле1 соотносится с полем2. Пример &#8212; у каждого человека свой номер паспорта. 1 человек- 1 паспорт. Тут отношение один-к-одному.</p>
<p>Один-к-многим указывает, что поле1 может соотносится как с полем2, так и с полем3, полемN&#8230; В книге приведён пример &#8212; у одного мужчины может быть много женщин и наоборот <img src='http://alexvolkov.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Автор юморист <img src='http://alexvolkov.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Один-к-многим самая распространённая связь между таблицами в нормализованных базах.</p>
<p>Отношение многие-к-многим бывает, когда нескольким значениям из одной таблицы соответствует несколько значений другой таблицы. Например, в категории блога может быть много постов, а у блога может быть много категорий. Еще такое отношение может встречаться в составных ключах. Такой связи следует избегать, поскольку она ведет к избыточности данных. В том-же вордпрессе категории и посты соотносятся через третью таблицу &#8212; wp_relationships.</p>
<p>На рисунке приведены условные обозначения всех трех отношений в нотации UML.</p>
<p><a href="http://alexvolkov.ru/wp-content/uploads/2011/11/3.png"><img class="alignnone size-full wp-image-1942" title="Условные обозначения отношений" src="http://alexvolkov.ru/wp-content/uploads/2011/11/3.png" alt="" width="416" height="331" /></a></p>
<p>Создание структуры базы данных (схема) и отношений между таблицами можно ускорить, использую различные CASE-средства. В конце будет ссылка на mysql workbench, бесплатную кроссплатформенную программу.</p>
<h3>На почитать:</h3>
<ul>
<li><a title="Нормальные формы" href="http://ru.wikipedia.org/wiki/%D0%9D%D0%BE%D1%80%D0%BC%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D0%B1%D0%B0%D0%B7_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85">Нормальные формы на вики</a></li>
<li><a href="http://support.microsoft.com/kb/283878/ru">Основные приемы нормализации от мелкомягких</a>. Кстати, это не далеко не первый годный материал, который я нашел у них в knowledge base. Туфту не пишут <img src='http://alexvolkov.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </li>
<li><a href="http://boyskodd.ru/">Аскетичный сайт с кучей теории по реляционным субд и реляционной алгебре</a></li>
<li><a title="скачать mysql workbench" href="http://www.mysql.com/downloads/workbench/">Mysql Workbench</a></li>
</ul>
<h2  class="related_post_title">На закуску.</h2><ul class="related_post"><li><a href="http://alexvolkov.ru/database-denormalization.html" title="Денормализация базы данных">Денормализация базы данных</a></li><li><a href="http://alexvolkov.ru/database-normalization-third-normal-form.html" title="Нормализация баз данных: третья нормальная форма">Нормализация баз данных: третья нормальная форма</a></li><li><a href="http://alexvolkov.ru/database-normalization-second-normal-form.html" title="Нормализация баз данных: вторая нормальная форма">Нормализация баз данных: вторая нормальная форма</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://alexvolkov.ru/database-normalizatio.html/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		<feedburner:origLink>http://alexvolkov.ru/database-normalizatio.html</feedburner:origLink></item>
		<item>
		<title>Вложенные SQL запросы: одновременное добавление одинарных и множественных строк в INSERT</title>
		<link>http://feedproxy.google.com/~r/AlexVolkov/~3/Kenv_OpfxUU/embedded-sql-statements-the-simultaneous-addition-of-single-and-multiple-rows-in-the-insert.html</link>
		<comments>http://alexvolkov.ru/embedded-sql-statements-the-simultaneous-addition-of-single-and-multiple-rows-in-the-insert.html#comments</comments>
		<pubDate>Tue, 04 Oct 2011 09:11:12 +0000</pubDate>
		<dc:creator>Alex Volkov</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Скрипты]]></category>
		<category><![CDATA[Mysql]]></category>
		<category><![CDATA[nested queries]]></category>
		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://alexvolkov.ru/?p=1892</guid>
		<description><![CDATA[Понадобилось для одной задачи сделать выборку из таблицы А по определенным условиям и вставить ее в таблицу B. Можно особо не заморачиваться, сделать SELECT  в переменную, потом пройтись циклом по INSERT и все. Но это не очень красивое решение. Очень запросов много + на переменные память расходуется. Проще использовать вложенные запросы, они же nested queries. [...]]]></description>
			<content:encoded><![CDATA[<p>Понадобилось для одной задачи сделать выборку из таблицы А по определенным условиям и вставить ее в таблицу B.<br />
Можно особо не заморачиваться, сделать SELECT  в переменную, потом пройтись циклом по INSERT и все.</p>
<p>Но это не очень красивое решение. Очень запросов много + на переменные память расходуется. Проще использовать вложенные запросы, они же nested queries. Но тут возникает проблемка -  если вставлять  только данные из INSERT, то все ок, но если добавлять еще и какие-нибудь неизменные значения, то выдается <em>Subquery returned more than 1 value.<br />
</em><br />
Чтобы не обьяснять на пальцах &#8212; сама таблица B</p>
<pre class="brush:sql">CREATE TEMPORARY TABLE `B` (
  `status` TINYINT(4) NULL DEFAULT NULL ,
  `pair` TEXT NULL DEFAULT NULL ,
)
ENGINE = MyISAM
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci;</pre>
<p>Копируем из таблицы A и вставляем в B так</p>
<pre class="brush:sql">INSERT INTO `B` (`pair`)
            SELECT `pair` FROM `A` ORDER BY RAND() LIMIT 100;</pre>
<p>Если поле status имеет неизменное значение, например 123, то просто вот так уже не вставить</p>
<pre class="brush:sql">INSERT INTO `B` (`status`, `pair`) VALUES (
            (SELECT `pair` FROM `A` ORDER BY RAND() LIMIT 100),
            123);</pre>
<p>Не совсем красивое решение нашел</p>
<pre class="brush:sql">UPDATE `B` SET `status` = '123' WHERE 1=1;</pre>
<p>Но хотелось бы в одну строку все заделать. Отпишитесь плиз в коментах, кто знает, как реализовать.</p>
<h2  class="related_post_title">На закуску.</h2><ul class="related_post"><li><a href="http://alexvolkov.ru/the-script-for-tuning-mysql.html" title="Скрипт для тюнинга MYSQL">Скрипт для тюнинга MYSQL</a></li><li><a href="http://alexvolkov.ru/mysql-rand-how-to-get-a-random-line-from-db.html" title="MYSQL RAND(), как получить рандомную строку из БД">MYSQL RAND(), как получить рандомную строку из БД</a></li><li><a href="http://alexvolkov.ru/robkijj-tar.html" title="Робкий tar )">Робкий tar )</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://alexvolkov.ru/embedded-sql-statements-the-simultaneous-addition-of-single-and-multiple-rows-in-the-insert.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://alexvolkov.ru/embedded-sql-statements-the-simultaneous-addition-of-single-and-multiple-rows-in-the-insert.html</feedburner:origLink></item>
		<item>
		<title>Проблемы с сериализацией массивов</title>
		<link>http://feedproxy.google.com/~r/AlexVolkov/~3/CHCrQVCdgMg/problems-with-the-serialization-of-arrays.html</link>
		<comments>http://alexvolkov.ru/problems-with-the-serialization-of-arrays.html#comments</comments>
		<pubDate>Wed, 17 Aug 2011 15:03:29 +0000</pubDate>
		<dc:creator>Alex Volkov</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[unserialize]]></category>

		<guid isPermaLink="false">http://alexvolkov.ru/?p=1884</guid>
		<description><![CDATA[Иногда бывает надо сохранить массив с данными куда-то, чтобы потом его достать и прочитать. Есть две хорошие функции для этого &#8212; serialize и unserialize. И все бы ничего, но вот иногда массив не получается десериализовать назад &#8212; возвращается предательское bool(false) вместо заветного массивчика. Проблем может быть две &#8212; первая это включенная директива magic_quotes. Лечится примерно [...]]]></description>
			<content:encoded><![CDATA[<p>Иногда бывает надо сохранить массив с данными куда-то, чтобы потом его достать и прочитать. Есть две хорошие функции для этого &#8212; serialize и unserialize. И все бы ничего, но вот иногда массив не получается десериализовать назад &#8212; возвращается предательское bool(false) вместо заветного массивчика.</p>
<p>Проблем может быть две &#8212; первая это включенная директива magic_quotes. Лечится примерно так -</p>
<pre class="brush:php">(get_magic_quotes_gpc()) ? stripslashes(unserialize($variable)) : unserialize($variable);</pre>
<p>За работу кода не отвечаю, но думаю мысль понятна.</p>
<p>Второй вариант, с которым втух я на несколько часов, это переносы строки. Если массив имеет в себе ячейку, в которой несколько строк, то он нифига не сериализуется взад, а выдаст false. Лечится убиванием \r\n</p>
<pre class="brush:php">$str = preg_replace("/\n/", "", $str);
$str = preg_replace("/\r/", "", $str);</pre>
<h2  class="related_post_title">На закуску.</h2><ul class="related_post"><li><a href="http://alexvolkov.ru/php-debugging-and-profiling.html" title="Профилирование и отладка PHP скриптов">Профилирование и отладка PHP скриптов</a></li><li><a href="http://alexvolkov.ru/class-to-work-with-the-service-reduction-options.html" title="Класс для работы с сервисами сокращения ссылок">Класс для работы с сервисами сокращения ссылок</a></li><li><a href="http://alexvolkov.ru/a-simple-way-to-test-the-process-on-the-existence-of.html" title="Простой способ проверки процесса на существование">Простой способ проверки процесса на существование</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://alexvolkov.ru/problems-with-the-serialization-of-arrays.html/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://alexvolkov.ru/problems-with-the-serialization-of-arrays.html</feedburner:origLink></item>
		<item>
		<title>Считаем, сколько строк кода в php проекте.</title>
		<link>http://feedproxy.google.com/~r/AlexVolkov/~3/7zsEQp9JQec/consider-how-many-lines-of-code-in-a-php-project.html</link>
		<comments>http://alexvolkov.ru/consider-how-many-lines-of-code-in-a-php-project.html#comments</comments>
		<pubDate>Tue, 17 May 2011 22:34:05 +0000</pubDate>
		<dc:creator>Alex Volkov</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[bash]]></category>

		<guid isPermaLink="false">http://alexvolkov.ru/?p=1876</guid>
		<description><![CDATA[Упало в ридер несколько записей(раз, двас, трис), как посчитать строчки в си проектах и стало интересно, сколько же строчек я накропал для одного проекта. Оказалось, 5060, не считая js и css всяких. Сама команда: find . -type f -name "*.php" -exec wc -l {} +; На закуску.Простой способ проверки процесса на существованиеКак узнать статус процесса [...]]]></description>
			<content:encoded><![CDATA[<p>Упало в ридер несколько записей(<a href="http://www.commandlinefu.com/commands/view/8394/how-many-lines-in-your-c-project">раз</a>, <a href="http://www.commandlinefu.com/commands/view/8399/how-many-lines-in-your-c-project">двас</a>, <a href="http://www.commandlinefu.com/commands/view/8397/how-many-lines-in-your-c-project">трис</a>), как посчитать строчки в си проектах и стало интересно, сколько же строчек я накропал для одного проекта. Оказалось, 5060, не считая js и css всяких.</p>
<p>Сама команда:</p>
<pre class="brush:shell">find . -type f -name "*.php" -exec wc -l {} +;</pre>
<h2  class="related_post_title">На закуску.</h2><ul class="related_post"><li><a href="http://alexvolkov.ru/a-simple-way-to-test-the-process-on-the-existence-of.html" title="Простой способ проверки процесса на существование">Простой способ проверки процесса на существование</a></li><li><a href="http://alexvolkov.ru/kak-uznat-status-processa-po-pid.html" title="Как узнать статус процесса по pid">Как узнать статус процесса по pid</a></li><li><a href="http://alexvolkov.ru/organizaciya-bekapa-na-serverakh.html" title="Организация бекапа на серверах">Организация бекапа на серверах</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://alexvolkov.ru/consider-how-many-lines-of-code-in-a-php-project.html/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		<feedburner:origLink>http://alexvolkov.ru/consider-how-many-lines-of-code-in-a-php-project.html</feedburner:origLink></item>
	</channel>
</rss><!-- This Quick Cache file was built for (  alexvolkov.ru/feed ) in 0.79673 seconds, on May 17th, 2012 at 10:59 pm UTC. --><!-- This Quick Cache file will automatically expire ( and be re-built automatically ) on May 17th, 2012 at 11:59 pm UTC -->

