<?xml version="1.0" encoding="utf-8"?>
<feed version="0.3" xmlns="http://purl.org/atom/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="zh-tw"> 
<title>Hami 網誌</title> 
<link rel="alternate" type="text/html" href="http://plog.tcc.edu.tw/blog/3" /> 
	 
	<modified>2008-08-19T21:58:36+0800</modified> 
<tagline>&lt;p&gt;Linux,PHP,Postgresql,MySQL ..開放源碼心得記錄&lt;/p&gt;
</tagline> 
<generator url="http://www.lifetype.net/" version="1.2">LifeType</generator> 
 
<copyright>Copyright (c) hami</copyright> 
  
 <entry> 
 <id>tag:plog.tcc.edu.tw,2008-08-19:44800</id>
 <title>轉貼 HOWTO: smooth CVS to SVN migration (and back again)</title> 
 <link rel="alternate" type="text/html" href="http://plog.tcc.edu.tw/post/3/44800" /> 
  
 <modified>2008-08-19T21:58:36+0800</modified> 
 <issued>2008-08-19T21:58:36+0800</issued> 
 <created>2008-08-19T21:58:36+0800</created> 
 <summary type="text/plain">  This page explains how I migrated the  VideoLAN  CVS repositories to Subversion while still allowing anonymous CVS access for users who did not want to move to Subversion. If you are a CVS user ...</summary> 
 <author> 
  
 <name>hami</name> 
 <url>http://plog.tcc.edu.tw/blog/3</url> 
 <email>cik@boe.tcc.edu.tw</email> 
</author> 
<dc:subject>
伺服器管理 
</dc:subject> 
 <content type="text/html" mode="escaped" xml:lang="zh-tw" xml:base="http://plog.tcc.edu.tw/blog/3"> 
 &lt;p&gt; This page explains how I migrated the &lt;a href=&quot;http://www.videolan.org/&quot;&gt;VideoLAN&lt;/a&gt; CVS repositories to Subversion while still allowing anonymous CVS access for users who did not want to move to Subversion. If you are a CVS user and have not yet fallen in love with &lt;a href=&quot;http://subversion.tigris.org/&quot;&gt;Subversion&lt;/a&gt;, I suggest you have a look at this excellent project. In fact, I recommend to be familiar with Subversion before reading this document, because I may have missed important things.&lt;/p&gt; &lt;p&gt; The idea is to migrate the CVS repository to a Subversion repository using &lt;code&gt;cvs2svn&lt;/code&gt;, disable CVS accounts (except read-only accounts such as anonymous) and set up post-commit hooks to replicate SVN commits back to the CVS repository. &lt;/p&gt; &lt;h2&gt; First step: &lt;code&gt;cvs2svn&lt;/code&gt; &lt;/h2&gt; &lt;p&gt; Here are the preparatory steps to migrate a CVS module &lt;code&gt;wooyay&lt;/code&gt; from the CVS root &lt;code&gt;/cvs/stuff&lt;/code&gt; to a new SVN repository &lt;code&gt;/svn/wooyay&lt;/code&gt;: &lt;/p&gt; &lt;table cellpadding=&quot;0&quot; cellspacing=&quot;5&quot; class=&quot;leftmenu&quot;&gt;     &lt;tbody&gt;         &lt;tr&gt;             &lt;td class=&quot;nowrap&quot; valign=&quot;top&quot;&gt;       &lt;code&gt;$ &lt;strong&gt;svnadmin create /svn/wooyay&lt;/strong&gt;&lt;br /&gt;             $ &lt;strong&gt;cvs2svn -s /svn/wooyay /cvs/stuff/wooyay&lt;/strong&gt;&lt;br /&gt;             $ &lt;strong&gt;svn ls file:///svn/wooyay&lt;/strong&gt;&lt;br /&gt;             branches/&lt;br /&gt;             tags/&lt;br /&gt;             trunk/&lt;br /&gt;             $&lt;/code&gt;     &lt;/td&gt;         &lt;/tr&gt;     &lt;/tbody&gt; &lt;/table&gt; &lt;p&gt; That&amp;rsquo;s all! Your SVN repository is created. The default layout is a bit special but quite handy: tags are in &lt;code&gt;tags/&lt;/code&gt;, branches are in &lt;code&gt;branches/&lt;/code&gt;, and HEAD is &lt;code&gt;trunk&lt;/code&gt;. &lt;/p&gt; &lt;p&gt; &lt;strong&gt;Don&amp;rsquo;t forget to backup your old CVS tree!&lt;/strong&gt; It might be useful if something ever gets wrong. &lt;/p&gt; &lt;h2&gt; Repository cleaning &lt;/h2&gt; &lt;p&gt; Now that your repository is created, you can use Subversion&amp;rsquo;s magical powers to do whatever you want to the repository, such as removing and renaming branches or tags. These steps are not mandatory but you might find them convenient. &lt;/p&gt; &lt;p&gt; CVS branch names cannot start with a digit or contain periods, and you end up with branches called &lt;code&gt;v1_2_3&lt;/code&gt; instead of &lt;code&gt;1.2.3&lt;/code&gt;. And I don&amp;rsquo;t like that. Here is an example of what I would do: &lt;/p&gt; &lt;table cellpadding=&quot;0&quot; cellspacing=&quot;5&quot; class=&quot;leftmenu&quot;&gt;     &lt;tbody&gt;         &lt;tr&gt;             &lt;td class=&quot;nowrap&quot; valign=&quot;top&quot;&gt;       &lt;code&gt;$ &lt;strong&gt;svn ls file:///svn/wooyay/branches&lt;/strong&gt;&lt;br /&gt;             test/&lt;br /&gt;             v1_0/&lt;br /&gt;             v2_0/&lt;br /&gt;             $ &lt;strong&gt;svn rm file:///svn/wooyay/branches/test -m &amp;quot;removed branch&amp;quot;&lt;/strong&gt;&lt;br /&gt;             $ &lt;strong&gt;svn mv file:///svn/wooyay/branches/v1_0 file:///svn/wooyay/branches/1.0 -m &amp;quot;renamed branch&amp;quot;&lt;/strong&gt;&lt;br /&gt;             $ &lt;strong&gt;svn mv file:///svn/wooyay/branches/v2_0 file:///svn/wooyay/branches/2.0 -m &amp;quot;renamed branch&amp;quot;&lt;/strong&gt;&lt;br /&gt;             $ &lt;strong&gt;svn ls file:///svn/wooyay/branches&lt;/strong&gt;&lt;br /&gt;             1.0/&lt;br /&gt;             2.0/&lt;br /&gt;             $&lt;/code&gt;     &lt;/td&gt;         &lt;/tr&gt;     &lt;/tbody&gt; &lt;/table&gt; &lt;p&gt; I also like to import .cvsignore files to Subversion properties and set the &amp;quot;Id&amp;quot; keyword properties for files containing the &amp;quot;$Id:&amp;quot; special string. If your repository is big, you might want to do this change only for &lt;code&gt;trunk/&lt;/code&gt; and the still active branches. &lt;/p&gt; &lt;table cellpadding=&quot;0&quot; cellspacing=&quot;5&quot; class=&quot;leftmenu&quot;&gt;     &lt;tbody&gt;         &lt;tr&gt;             &lt;td class=&quot;nowrap&quot; valign=&quot;top&quot;&gt;       &lt;code&gt;$ &lt;strong&gt;svn checkout file:///svn/wooyay/trunk workingdir&lt;/strong&gt;&lt;br /&gt;             $ &lt;strong&gt;cd workingdir/&lt;/strong&gt;&lt;br /&gt;             $ &lt;strong&gt;find -name .cvsignore | while read file; do&lt;br /&gt;             &amp;nbsp; &amp;nbsp; svn propset svn:ignore &amp;quot;`cat &amp;quot;$file&amp;quot;`&amp;quot; &amp;quot;`echo &amp;quot;$file&amp;quot; | sed &amp;#39;s,/[^/]*$,,&amp;#39;`&amp;quot;&lt;br /&gt;             &amp;nbsp; done&lt;/strong&gt;&lt;br /&gt;             $ &lt;strong&gt;find . -type f -a &amp;#39;(&amp;#39; -path &amp;#39;*/.*&amp;#39; -prune -o -print &amp;#39;)&amp;#39; | while read file; do&lt;br /&gt; &amp;nbsp; &amp;nbsp; if grep -q &amp;#39;\$Id:&amp;#39; &amp;quot;$file&amp;quot; &amp;amp;&amp;amp; ! svn propget svn:keywords &amp;quot;$file&amp;quot; | grep -q &amp;#39;^Id$&amp;#39;; then svn propset svn:keywords Id &amp;quot;$file&amp;quot;; fi&lt;br /&gt;             &amp;nbsp; done&lt;/strong&gt;&lt;br /&gt;             $ &lt;strong&gt;svn commit -m &amp;quot;imported svn:ignore and svn:keywords properties&amp;quot;&lt;/strong&gt;&lt;br /&gt;             $&lt;/code&gt;     &lt;/td&gt;         &lt;/tr&gt;     &lt;/tbody&gt; &lt;/table&gt; &lt;h2&gt; The post-commit hook &lt;/h2&gt; &lt;p&gt; This is the important part. My &lt;code&gt;&lt;strong&gt;&lt;a href=&quot;http://sam.zoy.org/writings/programming/svn_cvsinject&quot;&gt;svn_cvsinject&lt;/a&gt;&lt;/strong&gt;&lt;/code&gt; script can be used to reinject SVN commits into the old CVS directory. Use option &lt;code&gt;-r&lt;/code&gt; to specify the revision to reinject, and &lt;code&gt;-a&lt;/code&gt; to do branch aliases. In our example, this would be the contents of the &lt;code&gt;/svn/wooyay/hooks/post-commit&lt;/code&gt; file: &lt;/p&gt; &lt;table cellpadding=&quot;0&quot; cellspacing=&quot;5&quot; class=&quot;leftmenu&quot;&gt;     &lt;tbody&gt;         &lt;tr&gt;             &lt;td class=&quot;nowrap&quot; valign=&quot;top&quot;&gt;       &lt;code&gt;&lt;strong&gt;#!/bin/sh&lt;br /&gt;             REPOS=&amp;quot;$1&amp;quot;&lt;br /&gt;             REV=&amp;quot;$2&amp;quot;&lt;br /&gt;             &lt;a href=&quot;http://sam.zoy.org/writings/programming/svn_maillog&quot;&gt;svn_maillog&lt;/a&gt; &amp;quot;$REPOS&amp;quot; &amp;quot;$REV&amp;quot; &amp;quot;svn@localhost&amp;quot; &amp;quot;sam@localhost&amp;quot;&lt;br /&gt;             &lt;a href=&quot;http://sam.zoy.org/writings/programming/svn_cvsinject&quot;&gt;svn_cvsinject&lt;/a&gt; -r &amp;quot;$REV&amp;quot; &amp;quot;$REPOS&amp;quot; &amp;quot;/cvs/stuff/wooyay&amp;quot; \&lt;br /&gt;             &amp;nbsp; &amp;nbsp; -a &amp;quot;1.0/v1_0&amp;quot; -a &amp;quot;2.0/v2_0&amp;quot; &amp;amp;&lt;br /&gt;             exit 0&lt;/strong&gt;&lt;/code&gt;     &lt;/td&gt;         &lt;/tr&gt;     &lt;/tbody&gt; &lt;/table&gt; &lt;p&gt; It is advisable to run &lt;code&gt;svn_cvsinject&lt;/code&gt; in the background because it can take a long time to finish. Also, make sure that all users with commit rights (including the user svnserve might run as) have write permissions on the CVS repository. &lt;/p&gt; &lt;p&gt; Here are the current &lt;code&gt;svn_cvsinject&lt;/code&gt; features: &lt;/p&gt; &lt;ul&gt;&lt;li&gt; support for file creation and removal &lt;/li&gt;&lt;li&gt; support for directory creation and removal &lt;/li&gt;&lt;li&gt; support for simultaneous commits in different branches &lt;/li&gt;&lt;li&gt; support for branch aliases &lt;/li&gt;&lt;/ul&gt; &lt;p&gt; However, it also has the following current limitations: &lt;/p&gt; &lt;ul&gt;&lt;li&gt; no support for new branches &lt;/li&gt;&lt;li&gt; no user mapping when run from &lt;code&gt;svnserve&lt;/code&gt; (but the user is mentioned in the commit log) &lt;/li&gt;&lt;li&gt; concurrent calls may break things (use locks) &lt;/li&gt;&lt;li&gt; poor error handling &lt;/li&gt;&lt;/ul&gt; &lt;h2&gt; Conclusion &lt;/h2&gt; &lt;p&gt; It works for me (tm), but I&amp;rsquo;d be happy to learn of other successful installations. And please tell me of failures as well, so that I can fix bugs! &lt;/p&gt; If your CVS repository ever gets corrupted, you can reinject every SVN commit by restoring your backuped CVS tree and calling &lt;code&gt;svn_cvsinject&lt;/code&gt; again for every revision since you used &lt;code&gt;cvs2svn&lt;/code&gt; 
</content> 
</entry> 
 
 <entry> 
 <id>tag:plog.tcc.edu.tw,2006-08-20:15815</id>
 <title>docbook 配合 自訂的 css 輸出</title> 
 <link rel="alternate" type="text/html" href="http://plog.tcc.edu.tw/post/3/15815" /> 
  
 <modified>2006-08-20T16:29:00+0800</modified> 
 <issued>2006-08-20T16:29:00+0800</issued> 
 <created>2006-08-20T16:29:00+0800</created> 
 <summary type="text/plain"> 以 ubuntu 為例:  修改   /usr/share/sgml/docbook/stylesheet/dsssl/modular/html/docbook.dsl   ... (define all-element-number   (external-procedure &amp;quot;UNREGISTERED::James ...</summary> 
 <author> 
  
 <name>hami</name> 
 <url>http://plog.tcc.edu.tw/blog/3</url> 
 <email>cik@boe.tcc.edu.tw</email> 
</author> 
<dc:subject>
文件寫作 
</dc:subject> 
 <content type="text/html" mode="escaped" xml:lang="zh-tw" xml:base="http://plog.tcc.edu.tw/blog/3"> 
 &lt;p&gt;以 ubuntu 為例:&lt;/p&gt;&lt;p&gt;修改&lt;/p&gt;&lt;p&gt;&lt;font size=&quot;2&quot;&gt;/usr/share/sgml/docbook/stylesheet/dsssl/modular/html/docbook.dsl&lt;/font&gt;&lt;/p&gt;&lt;pre class=&quot;SCREEN&quot;&gt;...&lt;br /&gt;(define all-element-number&lt;br /&gt;  (external-procedure &amp;quot;UNREGISTERED::James Clark//Procedure::all-element-number&amp;quot;))&lt;br /&gt;; 從這開始&lt;br /&gt;(define %stylesheet%&lt;br /&gt;  &amp;quot;docbook.css&amp;quot;)&lt;br /&gt;&lt;br /&gt;(define %stylesheet-type%&lt;br /&gt;  &amp;quot;text/css&amp;quot;)&lt;br /&gt;; 到這結束&lt;br /&gt;(root&lt;br /&gt; (make sequence ...&lt;br /&gt;...&lt;/pre&gt;&lt;p&gt;撰寫 docbook.css ,放在目標文件下&lt;/p&gt;&lt;p&gt;參考文件 :&lt;/p&gt;&lt;p&gt;http://www.powermag.com.tw/docbook/book1.htm&lt;/p&gt; 
</content> 
</entry> 
 
 <entry> 
 <id>tag:plog.tcc.edu.tw,2006-08-02:15207</id>
 <title>unable to  load php_ldap.dll on php5.x</title> 
 <link rel="alternate" type="text/html" href="http://plog.tcc.edu.tw/post/3/15207" /> 
  
 <modified>2006-08-02T10:48:44+0800</modified> 
 <issued>2006-08-02T10:48:44+0800</issued> 
 <created>2006-08-02T10:48:44+0800</created> 
 <summary type="text/plain">php_ldap.dll needs the following dlls: 
 
ssleay32.dll 
libeay32.dll 
 
Copy them to the system32 directory.</summary> 
 <author> 
  
 <name>hami</name> 
 <url>http://plog.tcc.edu.tw/blog/3</url> 
 <email>cik@boe.tcc.edu.tw</email> 
</author> 
<dc:subject>
PHP 
</dc:subject> 
 <content type="text/html" mode="escaped" xml:lang="zh-tw" xml:base="http://plog.tcc.edu.tw/blog/3"> 
 php_ldap.dll needs the following dlls:&lt;br /&gt;
&lt;br /&gt;
ssleay32.dll&lt;br /&gt;
libeay32.dll&lt;br /&gt;
&lt;br /&gt;
Copy them to the system32 directory. 
</content> 
</entry> 
 
 <entry> 
 <id>tag:plog.tcc.edu.tw,2006-07-24:14567</id>
 <title>20 pro tips</title> 
 <link rel="alternate" type="text/html" href="http://plog.tcc.edu.tw/post/3/14567" /> 
  
 <modified>2006-07-24T16:50:07+0800</modified> 
 <issued>2006-07-24T16:50:07+0800</issued> 
 <created>2006-07-24T16:50:07+0800</created> 
 <summary type="text/plain"> Tips and tricks you should be using to give your work that all-important professional edge.   http://www.netmag.co.uk/zine/design-tutorials/20-pro-tips   </summary> 
 <author> 
  
 <name>hami</name> 
 <url>http://plog.tcc.edu.tw/blog/3</url> 
 <email>cik@boe.tcc.edu.tw</email> 
</author> 
<dc:subject>
CSS 
</dc:subject> 
 <content type="text/html" mode="escaped" xml:lang="zh-tw" xml:base="http://plog.tcc.edu.tw/blog/3"> 
 &lt;p&gt;Tips and tricks you should be using to give your work that all-important professional edge.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://www.netmag.co.uk/zine/design-tutorials/20-pro-tips&quot; title=&quot;http://www.netmag.co.uk/zine/design-tutorials/20-pro-tips&quot;&gt;http://www.netmag.co.uk/zine/design-tutorials/20-pro-tips&lt;/a&gt;&lt;/p&gt;&lt;p /&gt; 
</content> 
</entry> 
 
 <entry> 
 <id>tag:plog.tcc.edu.tw,2006-04-18:9575</id>
 <title>lifetype 使用者註冊問題</title> 
 <link rel="alternate" type="text/html" href="http://plog.tcc.edu.tw/post/3/9575" /> 
  
 <modified>2006-04-18T11:53:48+0800</modified> 
 <issued>2006-04-18T11:53:48+0800</issued> 
 <created>2006-04-18T11:53:48+0800</created> 
 <summary type="text/plain"> lifetype 對使用者的帳號採取較嚴格的限制,僅允許 A-Z a-z 0-9 的字元做為帳號，如要增加字元範圍可修改:      class/data/validator/usernamevalidator.class.php ...</summary> 
 <author> 
  
 <name>hami</name> 
 <url>http://plog.tcc.edu.tw/blog/3</url> 
 <email>cik@boe.tcc.edu.tw</email> 
</author> 
<dc:subject>
pLog 
</dc:subject> 
 <content type="text/html" mode="escaped" xml:lang="zh-tw" xml:base="http://plog.tcc.edu.tw/blog/3"> 
 &lt;div align=&quot;left&quot;&gt;lifetype 對使用者的帳號採取較嚴格的限制,僅允許 A-Z a-z 0-9 的字元做為帳號，如要增加字元範圍可修改:&lt;/div&gt;&lt;div align=&quot;left&quot;&gt;&lt;/div&gt;&lt;div align=&quot;left&quot;&gt;&lt;/div&gt;&lt;div align=&quot;left&quot;&gt;class/data/validator/usernamevalidator.class.php &lt;/div&gt;&lt;div align=&quot;left&quot;&gt;&lt;/div&gt;&lt;div align=&quot;left&quot;&gt; define( &amp;quot;ONLY_ALPHANUMERIC_REGEXP&amp;quot;,&amp;quot;^([A-Za-z0-9]*)$&amp;quot; );&lt;/div&gt;&lt;div align=&quot;right&quot;&gt;
&lt;/div&gt; 
</content> 
</entry> 
 
 <entry> 
 <id>tag:plog.tcc.edu.tw,2005-11-07:2683</id>
 <title>OPENLDAP 備份與還原</title> 
 <link rel="alternate" type="text/html" href="http://plog.tcc.edu.tw/post/3/2683" /> 
  
 <modified>2005-11-07T17:40:14+0800</modified> 
 <issued>2005-11-07T17:40:14+0800</issued> 
 <created>2005-11-07T17:40:14+0800</created> 
 <summary type="text/plain"> backup_ldap.sh 將每日 ldap 備份出來  #!/bin/bash 
 
the_date=`date &#039;+%m-%d-%y&#039;`  the_dc=&#039;dc=tcc&#039;  
the_name=/var/ldap_backup/ldap_backup_$the_date.bz2 
 
/usr/sbin/slapcat -f ...</summary> 
 <author> 
  
 <name>hami</name> 
 <url>http://plog.tcc.edu.tw/blog/3</url> 
 <email>cik@boe.tcc.edu.tw</email> 
</author> 
<dc:subject>
伺服器管理 
</dc:subject> 
 <content type="text/html" mode="escaped" xml:lang="zh-tw" xml:base="http://plog.tcc.edu.tw/blog/3"> 
 &lt;p&gt;backup_ldap.sh 將每日 ldap 備份出來&lt;/p&gt;&lt;p&gt;#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
the_date=`date &#039;+%m-%d-%y&#039;`&lt;/p&gt;&lt;p&gt;the_dc=&#039;dc=tcc&#039;&lt;br /&gt;&lt;br /&gt;
the_name=/var/ldap_backup/ldap_backup_$the_date.bz2&lt;br /&gt;
&lt;br /&gt;
/usr/sbin/slapcat -f /etc/openldap/slapd.conf -b &amp;quot;$the_dc&amp;quot; | bzip2 -9 &amp;gt; $the_name&lt;/p&gt;&lt;p /&gt;&lt;p&gt;還原:&lt;/p&gt;&lt;p&gt;bzip2 -d /var/ldap_backup/ldap_backup_11-07-05.bz2&lt;/p&gt;&lt;pre style=&quot;margin: 0em;&quot;&gt;&lt;font size=&quot;4&quot;&gt;slapadd -c -l /var/ldap_backup/ldap_backup_11-07-05&lt;/font&gt;&lt;/pre&gt; 
</content> 
</entry> 
 
 <entry> 
 <id>tag:plog.tcc.edu.tw,2005-10-28:2351</id>
 <title>利用 Web Editor 寫網誌</title> 
 <link rel="alternate" type="text/html" href="http://plog.tcc.edu.tw/post/3/2351" /> 
  
 <modified>2005-10-28T16:10:55+0800</modified> 
 <issued>2005-10-28T16:10:55+0800</issued> 
 <created>2005-10-28T16:10:55+0800</created> 
 <summary type="text/plain">    利用 Web Editor 寫網誌,參考網址       &amp;#160; http://plog.yejh.tc.edu.tw/index.php?op=ViewArticle&amp;amp;articleId=426&amp;amp;blogId=1 &amp;#160;&amp;#160;  </summary> 
 <author> 
  
 <name>hami</name> 
 <url>http://plog.tcc.edu.tw/blog/3</url> 
 <email>cik@boe.tcc.edu.tw</email> 
</author> 
<dc:subject>
pLog 
</dc:subject> 
 <content type="text/html" mode="escaped" xml:lang="zh-tw" xml:base="http://plog.tcc.edu.tw/blog/3"> 
 &lt;p&gt;   利用 Web Editor 寫網誌,參考網址 &lt;/p&gt;&lt;p&gt;   &lt;!--StartFragment --&gt;&amp;#160;&lt;a href=&quot;http://plog.yejh.tc.edu.tw/index.php?op=ViewArticle&amp;amp;articleId=426&amp;amp;blogId=1&quot;&gt;http://plog.yejh.tc.edu.tw/index.php?op=ViewArticle&amp;amp;articleId=426&amp;amp;blogId=1&lt;/a&gt;&amp;#160;&amp;#160; &lt;/p&gt; 
</content> 
</entry> 
 
 <entry> 
 <id>tag:plog.tcc.edu.tw,2005-10-26:2197</id>
 <title>FortiGate-400研習教材</title> 
 <link rel="alternate" type="text/html" href="http://plog.tcc.edu.tw/post/3/2197" /> 
  
 <modified>2005-10-26T08:49:30+0800</modified> 
 <issued>2005-10-26T08:49:30+0800</issued> 
 <created>2005-10-26T08:49:30+0800</created> 
 <summary type="text/plain"> bubble&#039;s weblog 的  FortiGate-400研習教材  </summary> 
 <author> 
  
 <name>hami</name> 
 <url>http://plog.tcc.edu.tw/blog/3</url> 
 <email>cik@boe.tcc.edu.tw</email> 
</author> 
<dc:subject>
網路管理 
</dc:subject> 
 <content type="text/html" mode="escaped" xml:lang="zh-tw" xml:base="http://plog.tcc.edu.tw/blog/3"> 
 &lt;p&gt;bubble&#039;s weblog 的 &lt;a href=&quot;http://plog.tcc.edu.tw/trackbacks/128/2034&quot;&gt;FortiGate-400研習教材&lt;/a&gt;&lt;/p&gt; 
</content> 
</entry> 
 
 <entry> 
 <id>tag:plog.tcc.edu.tw,2005-10-02:1601</id>
 <title>PostgreSQL Performance Tips</title> 
 <link rel="alternate" type="text/html" href="http://plog.tcc.edu.tw/post/3/1601" /> 
  
 <modified>2005-10-02T14:05:16+0800</modified> 
 <issued>2005-10-02T14:05:16+0800</issued> 
 <created>2005-10-02T14:05:16+0800</created> 
 <summary type="text/plain"> 取自:  http://chery.axonpro.sk/pgsql/chapters/performance/index.html
  

  

  
  PostgreSQL Performance Tips 
     

P OSTGRE SQL is an object-relational database under active ...</summary> 
 <author> 
  
 <name>hami</name> 
 <url>http://plog.tcc.edu.tw/blog/3</url> 
 <email>cik@boe.tcc.edu.tw</email> 
</author> 
<dc:subject>
postgresql 
</dc:subject> 
 <content type="text/html" mode="escaped" xml:lang="zh-tw" xml:base="http://plog.tcc.edu.tw/blog/3"> 
 &lt;p&gt;取自:&lt;/p&gt;&lt;p&gt;http://chery.axonpro.sk/pgsql/chapters/performance/index.html
&lt;/p&gt;&lt;p&gt;

&lt;/p&gt;&lt;p&gt;

&lt;/p&gt;&lt;p&gt;
&lt;/p&gt;&lt;h1 align=&quot;center&quot;&gt;PostgreSQL Performance Tips&lt;/h1&gt;
&lt;p align=&quot;center&quot;&gt;&lt;strong&gt; &lt;/strong&gt;&lt;/p&gt;

P&lt;small&gt;OSTGRE&lt;/small&gt;SQL is an object-relational database under active development
on the Internet. You can learn more by visiting http://www.postgresql.org.

&lt;p&gt;
In an ideal world, users would never need to be concerned about performance.
The system would tune itself. Unfortunately, we do not live in an ideal world.
An untuned database can be thousands of times slower than a tuned one, so it
pays to take steps to improve performance. This article shows you how to get
the optimal performance from your database.

&lt;/p&gt;&lt;p&gt;

&lt;/p&gt;&lt;h1&gt;&lt;a name=&quot;SECTION00010000000000000000&quot;&gt;
Indexes &lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;
When accessing a table, P&lt;small&gt;OSTGRE&lt;/small&gt;SQL normally reads from the beginning
of the table to the end, looking for relevant rows. With an index, it can quickly
find specific values in the index, then go directly to matching rows. In this
way, indexes allow fast retrieval of specific rows from a table.

&lt;/p&gt;&lt;p&gt;
For example, consider the query &lt;tt&gt;SELECT * FROM customer WHERE col =
43&lt;/tt&gt;&lt;em&gt;.&lt;/em&gt; Without an index, P&lt;small&gt;OSTGRE&lt;/small&gt;SQL must scan the entire table
looking for rows where &lt;em&gt;col&lt;/em&gt; equals &lt;em&gt;43.&lt;/em&gt; With an index on &lt;em&gt;col,&lt;/em&gt;
P&lt;small&gt;OSTGRE&lt;/small&gt;SQL can go directly to rows where &lt;em&gt;col&lt;/em&gt; equals &lt;em&gt;43,&lt;/em&gt;
bypassing all other rows.

&lt;/p&gt;&lt;p&gt;
For a large table, it can take minutes to check every row. Using an index, finding
a specific row takes fractions of a second.

&lt;/p&gt;&lt;p&gt;
Internally, P&lt;small&gt;OSTGRE&lt;/small&gt;SQL stores data in operating system files. Each
table has its own file, and data rows are stored one after another in the file.
An index is a separate file that is sorted by one or more columns. It contains
pointers into the table file, allowing rapid access to specific values in the
table. 

&lt;/p&gt;&lt;p&gt;
P&lt;small&gt;OSTGRE&lt;/small&gt;SQL does not create indexes automatically. Instead, users should
create them for columns frequently used in &lt;small&gt;WHERE&lt;/small&gt; clauses. 

&lt;/p&gt;&lt;p&gt;
To create an index, use the &lt;small&gt;CREATE INDEX&lt;/small&gt; command, as shown in this
figure.
&lt;tt&gt; 
&lt;br /&gt;
&lt;br /&gt;        test=&amp;gt; CREATE INDEX customer_custid_idx ON customer (customer_id);
&lt;br /&gt;        CREATE
&lt;/tt&gt; 
&lt;br /&gt;
&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;
In this example, &lt;em&gt;customer_custid_idx&lt;/em&gt; is the name of the index, &lt;em&gt;customer&lt;/em&gt;
is the table being indexed, and &lt;em&gt;customer_id&lt;/em&gt; is the column being indexed.
Although you can use any name for the index, it is good practice to use the
table and column names as part of the index name--for example, &lt;em&gt;customer_customer_id_idx&lt;/em&gt;
or &lt;em&gt;i_customer_custid.&lt;/em&gt; This index is useful only for finding rows in
&lt;em&gt;customer&lt;/em&gt; for specific &lt;em&gt;customer_ids.&lt;/em&gt; It cannot help when you are
accessing other columns, because indexes are sorted by a specific column.

&lt;/p&gt;&lt;p&gt;
You can create as many indexes as you wish. Of course, an index on a seldom-used
column is a waste of disk space. Also, performance can suffer if too many indexes
exist, because row changes require an update to each index.

&lt;/p&gt;&lt;p&gt;
It is possible to create an index spanning multiple columns. Multicolumn indexes
are sorted by the first indexed column. When the first column contains several
equal values, sorting continues using the second indexed column. Multicolumn
indexes are useful only on columns with many duplicate values. 

&lt;/p&gt;&lt;p&gt;
The command &lt;tt&gt;CREATE INDEX customer_age_gender_idx ON customer (age,
gender)&lt;/tt&gt; creates an index that is sorted by &lt;em&gt;age&lt;/em&gt; and, when several &lt;em&gt;age&lt;/em&gt;
rows have the same value, then sorted on &lt;em&gt;gender.&lt;/em&gt; This index can be used
by the query &lt;tt&gt;SELECT * FROM customer WHERE age = 36 AND gender = &#039;F&#039;&lt;/tt&gt;
and the query &lt;tt&gt;SELECT * FROM customer WHERE age = 36&lt;/tt&gt;&lt;em&gt;.&lt;/em&gt; 

&lt;/p&gt;&lt;p&gt;
The index &lt;em&gt;customer_age_gender_idx&lt;/em&gt; is useless if you wish to find rows
based only on &lt;em&gt;gender,&lt;/em&gt; however&lt;em&gt;.&lt;/em&gt; The &lt;em&gt;gender&lt;/em&gt; component of
the index can be used only after the &lt;em&gt;age&lt;/em&gt; value has been specified. Thus,
the query &lt;tt&gt;SELECT * FROM customer WHERE gender = &#039;F&#039;&lt;/tt&gt; cannot use the
index because it does not place a restriction on &lt;em&gt;age&lt;/em&gt;, which is the first
part of the index.

&lt;/p&gt;&lt;p&gt;
Indexes can be useful for columns involved in joins, too. They can even be employed
to speed up some &lt;small&gt;ORDER BY &lt;/small&gt; clauses. 

&lt;/p&gt;&lt;p&gt;
To remove an index, use the &lt;small&gt;DROP INDEX&lt;/small&gt; command. See the &lt;small&gt;CREATE&lt;/small&gt;_&lt;small&gt;INDEX&lt;/small&gt;
and &lt;small&gt;DROP&lt;/small&gt;_&lt;small&gt;INDEX&lt;/small&gt; manual pages for more information.

&lt;/p&gt;&lt;p&gt;

&lt;/p&gt;&lt;h1&gt;&lt;a name=&quot;SECTION00020000000000000000&quot;&gt;
Unique Indexes &lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;
Unique indexes resemble ordinary indexes, except that they prevent duplicate
values from occurring in the table. This figure shows the creation of one table
and a unique index.
&lt;tt&gt; 
&lt;br /&gt;
&lt;br /&gt;        test=&amp;gt; CREATE TABLE duptest (channel INTEGER);
&lt;br /&gt;        CREATE
&lt;br /&gt;        test=&amp;gt; CREATE UNIQUE INDEX duptest_channel_idx ON duptest (channel);
&lt;br /&gt;        CREATE
&lt;br /&gt;        test=&amp;gt; INSERT INTO duptest VALUES (1);
&lt;br /&gt;        INSERT 130220 1
&lt;br /&gt;        test=&amp;gt; INSERT INTO duptest VALUES (1);
&lt;br /&gt;        ERROR:  Cannot insert a duplicate key into unique index duptest_channel_idx
&lt;/tt&gt; 
&lt;br /&gt;
&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;
The index is unique because of the keyword &lt;small&gt;UNIQUE&lt;/small&gt;. The remaining queries
try to insert a duplicate value, but the unique index prevents this and displays
an appropriate error message.

&lt;/p&gt;&lt;p&gt;
Sometimes unique indexes are created only to prevent duplicate values, not for
performance reasons. Multicolumn unique indexes ensure that the combination
of indexed columns remains unique. Unique indexes do allow multiple &lt;small&gt;NULL
&lt;/small&gt; values, however. Unique indexes both speed data access and prevent duplicates.

&lt;/p&gt;&lt;p&gt;

&lt;/p&gt;&lt;h1&gt;&lt;a name=&quot;SECTION00030000000000000000&quot;&gt;
C&lt;small&gt;LUSTER  &lt;/small&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;
The &lt;small&gt;CLUSTER&lt;/small&gt; command reorders the table file to match the ordering of
an index. This specialized command is valuable when performance is critical
and the indexed column has many duplicate values. 

&lt;/p&gt;&lt;p&gt;
For example, suppose the column &lt;em&gt;customer.age&lt;/em&gt; has many duplicate values,
and the query &lt;tt&gt;SELECT * FROM customer WHERE age = 98&lt;/tt&gt; is executed.
An index on &lt;em&gt;age&lt;/em&gt; allows rapid retrieval of the row locations from the
index. If thousands of matching rows exist, however, they may be scattered in
the table file, requiring many disk accesses to retrieve them. C&lt;small&gt;LUSTER&lt;/small&gt;
reorders the table, placing duplicate values next to each other. This speeds
access for large queries accessing many duplicate values. 

&lt;/p&gt;&lt;p&gt;
C&lt;small&gt;LUSTER&lt;/small&gt; even helps with range queries like &lt;em&gt;col &amp;gt;=
3&lt;/em&gt; &lt;small&gt;AND&lt;/small&gt; &lt;em&gt;col &amp;lt;= 5.&lt;/em&gt; The command places these rows next
to each other on disk, speeding indexed lookups.

&lt;/p&gt;&lt;p&gt;
In addition, &lt;small&gt;CLUSTER&lt;/small&gt; can also speed &lt;small&gt;ORDER BY &lt;/small&gt; processing.
See the &lt;small&gt;CLUSTER&lt;/small&gt; manual page for more information.  

&lt;/p&gt;&lt;p&gt;

&lt;/p&gt;&lt;h1&gt;&lt;a name=&quot;SECTION00040000000000000000&quot;&gt;
V&lt;small&gt;ACUUM &lt;/small&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;
When P&lt;small&gt;OSTGRE&lt;/small&gt;SQL updates a row, it keeps the original copy of the row
in the table file and writes a new one. The original row, marked as expired,
is used by other transactions still viewing the database in its prior state.
Deletions are similarly marked as expired, but not removed from the table file.

&lt;/p&gt;&lt;p&gt;
The &lt;small&gt;VACUUM&lt;/small&gt; command removes expired rows from the file. In the process,
it moves rows from the end of the table into the expired spots, thereby compacting
the table file. 

&lt;/p&gt;&lt;p&gt;
You should run &lt;small&gt;VACUUM&lt;/small&gt; periodically to clean out expired rows. For tables
that are heavily modified, it is useful to run &lt;small&gt;VACUUM&lt;/small&gt; every night in
an automated manner. For tables with few modifications, &lt;small&gt;VACUUM&lt;/small&gt; should
be run less frequently. The command exclusively locks the table while processing.

&lt;/p&gt;&lt;p&gt;
You can run &lt;small&gt;VACUUM&lt;/small&gt; in two ways. Using &lt;small&gt;VACUUM&lt;/small&gt; alone
vacuums all tables in the database. Using &lt;small&gt;VACUUM&lt;/small&gt; &lt;em&gt;tablename&lt;/em&gt; vacuums
a single table.

&lt;/p&gt;&lt;p&gt;

&lt;/p&gt;&lt;h1&gt;&lt;a name=&quot;SECTION00050000000000000000&quot;&gt;
V&lt;small&gt;ACUUM &lt;/small&gt;A&lt;small&gt;NALYZE &lt;/small&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;
The &lt;small&gt;VACUUM&lt;/small&gt; &lt;small&gt;ANALYZE&lt;/small&gt; command resembles &lt;small&gt;VACUUM,&lt;/small&gt; but
also collects statistics about each column&#039;s proportion of duplicate values
and the maximum and minimum values. P&lt;small&gt;OSTGRE&lt;/small&gt;SQL uses this information
when deciding how to efficiently execute complex queries. You should run &lt;small&gt;VACUUM
ANALYZE&lt;/small&gt; when a table is initially loaded and when a table&#039;s data changes dramatically.

&lt;/p&gt;&lt;p&gt;
The &lt;small&gt;VACUUM&lt;/small&gt; manual page shows all of the &lt;small&gt;VACUUM&lt;/small&gt; options.  

&lt;/p&gt;&lt;p&gt;

&lt;/p&gt;&lt;h1&gt;&lt;a name=&quot;SECTION00060000000000000000&quot;&gt;
E&lt;small&gt;XPLAIN &lt;/small&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;
E&lt;small&gt;XPLAIN&lt;/small&gt; causes P&lt;small&gt;OSTGRE&lt;/small&gt;SQL to display how a query will be executed,
rather than executing it. As an example, this figure shows a &lt;small&gt;SELECT&lt;/small&gt;
query preceeded by the word &lt;small&gt;EXPLAIN. &lt;/small&gt;
&lt;tt&gt; 
&lt;br /&gt;
&lt;br /&gt;        test=&amp;gt; EXPLAIN SELECT customer_id FROM customer;
&lt;br /&gt;        NOTICE:  QUERY PLAN:
&lt;br /&gt;         
&lt;br /&gt;        Seq Scan on customer  (cost=0.00..15.00 rows=1000 width=4)
&lt;br /&gt;         
&lt;br /&gt;        EXPLAIN
&lt;/tt&gt; 
&lt;br /&gt;
&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;
In the figure, P&lt;small&gt;OSTGRE&lt;/small&gt;SQL reports a &lt;em&gt;sequential scan &lt;/em&gt; will be
used on &lt;em&gt;customer,&lt;/em&gt; meaning it will read the entire table. The &lt;em&gt;cost&lt;/em&gt;
is an estimate of the work required to execute the query (the numbers are only
meaningful for comparison). The &lt;em&gt;rows&lt;/em&gt; indicates the number of result rows
expected. The &lt;em&gt;width&lt;/em&gt; is the number of bytes per row.

&lt;/p&gt;&lt;p&gt;
The next figure shows more interesting examples of &lt;small&gt;EXPLAIN.&lt;/small&gt;
&lt;tt&gt; 
&lt;br /&gt;
&lt;br /&gt;        test=&amp;gt; EXPLAIN SELECT customer_id FROM customer WHERE customer_id = 55;
&lt;br /&gt;        NOTICE:  QUERY PLAN:
&lt;br /&gt;         
&lt;br /&gt;        Seq Scan on customer  (cost=0.00..22.50 rows=10 width=4)
&lt;br /&gt;         
&lt;br /&gt;        EXPLAIN
&lt;br /&gt;        test=&amp;gt; VACUUM ANALYZE customer;
&lt;br /&gt;        VACUUM
&lt;br /&gt;        test=&amp;gt; EXPLAIN SELECT customer_id FROM customer WHERE customer_id = 55;
&lt;br /&gt;        NOTICE:  QUERY PLAN:
&lt;br /&gt;         
&lt;br /&gt;        Seq Scan on customer  (cost=0.00..17.50 rows=1 width=4)
&lt;br /&gt;         
&lt;br /&gt;        EXPLAIN
&lt;br /&gt;        test=&amp;gt; CREATE UNIQUE INDEX customer_custid_idx ON customer (customer_id);
&lt;br /&gt;        CREATE
&lt;br /&gt;        test=&amp;gt; EXPLAIN SELECT customer_id FROM customer WHERE customer_id = 55;
&lt;br /&gt;        NOTICE:  QUERY PLAN:
&lt;br /&gt;         
&lt;br /&gt;        Index Scan using customer_custid_idx on customer  (cost=0.00..2.01 rows=1 width=4)
&lt;br /&gt;         
&lt;br /&gt;        EXPLAIN
&lt;br /&gt;        test=&amp;gt; EXPLAIN SELECT customer_id FROM customer;
&lt;br /&gt;        NOTICE:  QUERY PLAN:
&lt;br /&gt;         
&lt;br /&gt;        Seq Scan on customer  (cost=0.00..15.00 rows=1000 width=4)
&lt;br /&gt;         
&lt;br /&gt;        EXPLAIN
&lt;br /&gt;        test=&amp;gt; EXPLAIN SELECT * FROM customer ORDER BY customer_id;
&lt;br /&gt;        NOTICE:  QUERY PLAN:
&lt;br /&gt;         
&lt;br /&gt;        Index Scan using customer_custid_idx on customer  (cost=0.00..42.00 rows=1000 width=4)
&lt;br /&gt;         
&lt;br /&gt;        EXPLAIN
&lt;/tt&gt; 
&lt;br /&gt;
&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;
The first &lt;small&gt;EXPLAIN&lt;/small&gt; shows a &lt;small&gt;SELECT&lt;/small&gt; with the restriction &lt;em&gt;customer_id
= 55.&lt;/em&gt; The command reports another sequential scan, but the restriction causes
P&lt;small&gt;OSTGRE&lt;/small&gt;SQL to estimate that ten rows will be returned. A &lt;small&gt;VACUUM
 ANALYZE &lt;/small&gt; command is then run, causing the next query to properly estimate
that one row will be returned instead of ten.  An index is created, and the
query rerun. This time, an &lt;em&gt;index scan &lt;/em&gt; is used, allowing P&lt;small&gt;OSTGRE&lt;/small&gt;SQL
to go directly to the rows where &lt;em&gt;customer_id&lt;/em&gt; equals &lt;em&gt;55.&lt;/em&gt; The next
&lt;small&gt;EXPLAIN&lt;/small&gt; shows a query with no &lt;small&gt;WHERE&lt;/small&gt; restriction. P&lt;small&gt;OSTGRE&lt;/small&gt;SQL
realizes that the index is useless and performs a sequential scan. The last
query has an &lt;small&gt;ORDER BY &lt;/small&gt; that matches an index, so P&lt;small&gt;OSTGRE&lt;/small&gt;SQL
uses an index scan. 

&lt;/p&gt;&lt;p&gt;
Even more complex queries can be studied using &lt;small&gt;EXPLAIN&lt;/small&gt;, as shown in
this figure.
&lt;tt&gt; 
&lt;br /&gt;
&lt;br /&gt;        test=&amp;gt; EXPLAIN SELECT * FROM tab1, tab2 WHERE col1 = col2;
&lt;br /&gt;        NOTICE:  QUERY PLAN:
&lt;br /&gt;         
&lt;br /&gt;        Merge Join  (cost=139.66..164.66 rows=10000 width=8)
&lt;br /&gt;          -&amp;gt;  Sort  (cost=69.83..69.83 rows=1000 width=4)
&lt;br /&gt;                -&amp;gt;  Seq Scan on tab2  (cost=0.00..20.00 rows=1000 width=4)
&lt;br /&gt;          -&amp;gt;  Sort  (cost=69.83..69.83 rows=1000 width=4)
&lt;br /&gt;                -&amp;gt;  Seq Scan on tab1  (cost=0.00..20.00 rows=1000 width=4)
&lt;br /&gt;         
&lt;br /&gt;        EXPLAIN
&lt;/tt&gt; 
&lt;br /&gt;
&lt;br /&gt;
&lt;/p&gt;&lt;p&gt;
In this example, &lt;em&gt;tab1&lt;/em&gt; and &lt;em&gt;tab2&lt;/em&gt; are joined on &lt;em&gt;col1&lt;/em&gt; and
&lt;em&gt;col2.&lt;/em&gt; Each table is sequentially scanned, and the result sorted. The
two results are then &lt;em&gt;merge joined &lt;/em&gt; to produce output. It also supports
&lt;em&gt;hash join &lt;/em&gt; and &lt;em&gt;nested loop&lt;/em&gt;  join methods. It chooses the join
method it believes to be the fastest.  

&lt;/p&gt;&lt;p&gt;

&lt;/p&gt;&lt;h1&gt;&lt;a name=&quot;SECTION00070000000000000000&quot;&gt;
Summary&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;
A variety of tools are available to speed up P&lt;small&gt;OSTGRE&lt;/small&gt;SQL queries. Although
their use is not required, they can produce huge improvements in query speed.
Another article outlines more steps that database administrators can take to
improve performance. 

&lt;/p&gt;&lt;p&gt;

&lt;/p&gt;&lt;h1&gt;&lt;a name=&quot;SECTION00080000000000000000&quot;&gt;
About the Author&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;
Bruce Momjian is Vice-President of Database Development at Great Bridge,
LLC, http://www.greatbridge.com and author of &lt;em&gt;PostgreSQL:
Introduction and Concepts,&lt;/em&gt; ©2001, Addison-Wesley, ISBN
0-201-70331-9. This article is taken from that book. The web site for
the book is http://www.postgresql.org/docs/awbook.html.

&lt;/p&gt;&lt;p&gt;
&lt;br /&gt;

&lt;/p&gt;&lt;div id=&quot;google-toolbar-tooltip&quot; style=&quot;border: 1px outset rgb(0, 0, 0); padding: 2px; background: rgb(255, 255, 221) none repeat scroll 0% 50%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; font-family: serif; font-style: normal; font-variant: normal; font-weight: normal; font-size: medium; line-height: normal; font-size-adjust: none; font-stretch: normal; position: absolute; color: rgb(17, 17, 17); text-align: left; text-decoration: none; text-indent: 0pt; text-transform: none; z-index: 2147483647; left: 427px; top: 698px; display: none;&quot;&gt;&lt;center&gt;&lt;small&gt;customer: 顧客; 主顧; 買主; 傢伙; 客&lt;/small&gt;&lt;/center&gt;&lt;/div&gt; 
</content> 
</entry> 
 
 <entry> 
 <id>tag:plog.tcc.edu.tw,2005-09-28:1571</id>
 <title>postgresql FAQ</title> 
 <link rel="alternate" type="text/html" href="http://plog.tcc.edu.tw/post/3/1571" /> 
  
 <modified>2005-09-28T23:25:03+0800</modified> 
 <issued>2005-09-28T23:25:03+0800</issued> 
 <created>2005-09-28T23:25:03+0800</created> 
 <summary type="text/plain">http://sraapowergres.com/en/newsletter/issue_01/faq.inc.html This FAQ is geared for those people interested in the more common
issues that one encounters with PostgreSQL. It will grow in time ...</summary> 
 <author> 
  
 <name>hami</name> 
 <url>http://plog.tcc.edu.tw/blog/3</url> 
 <email>cik@boe.tcc.edu.tw</email> 
</author> 
<dc:subject>
postgresql 
</dc:subject> 
 <content type="text/html" mode="escaped" xml:lang="zh-tw" xml:base="http://plog.tcc.edu.tw/blog/3"> 
 http://sraapowergres.com/en/newsletter/issue_01/faq.inc.html&lt;p&gt;This FAQ is geared for those people interested in the more common
issues that one encounters with PostgreSQL. It will grow in time with
every issue by adding 10 new FAQ&#039;s to our list. They have been tested
against the 7.x version of PostgreSQL but they are equally valid for
the 8.x series too.&lt;/p&gt;
&lt;hr /&gt;

&lt;p&gt;&lt;b&gt;Q:&lt;/b&gt;&lt;i&gt;How do I datamine log files when the information loaded may already be present i.e. what do I do about data duplication?&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;One easy way is to upload the data into a table and then create a view using the DISTINCT clause that removes duplicate records:
&lt;br /&gt;
&lt;/p&gt;&lt;pre&gt;CREATE TABLE mytable(comments text);&lt;br /&gt;CREATE VIEW v_mytable AS SELECT DISTINCT ON(comments) oid,comments FROM mychild;&lt;br /&gt;copy mytable from logfile.txt&lt;/pre&gt;
You can now query the view v_mytable which returns only unique records:
&lt;pre&gt;SELECT comments FROM v_mytable ORDER BY oid;&lt;/pre&gt;

&lt;hr /&gt;
&lt;p&gt;&lt;b&gt;Q:&lt;/b&gt;&lt;i&gt;How do I get a date, either from the past or in the future that is relative to a particular one such as today&#039;s date?&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;There are two techniques demonstrated here. The first method
involves using a variation of either of these two statements which
returns the date 30 days (1 month) from today:
&lt;/p&gt;&lt;pre&gt;SELECT now() + &#039;1 month&#039;::interval;&lt;br /&gt;SELECT now() + &#039;30 days&#039;::interval;&lt;/pre&gt;
The second method involves using the function date_mii() which returns the same date as the above example:
&lt;pre&gt;SELECT date_mii(date(now()),-30);&lt;/pre&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;b&gt;Q:&lt;/b&gt;&lt;i&gt;How do I load a file into a database?&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;One method of importing a file into a database is to take advantage
of PostgreSQL&#039;s Large Object mechanism which can load form of text or
binary file. Manipulating a large object can be carried out by psql the
PostgreSQL console client.
&lt;br /&gt;
The following is an example of an import. Successful imports always return the Object Identification number (oid).
&lt;/p&gt;&lt;pre&gt;psql -Umyuser -c &amp;quot;lo_import &#039;myphoto.png&#039; &#039;a picture of me&#039; &amp;quot; mydatabase&lt;/pre&gt;

This is an example of an export and assumes the oid is 12345:
&lt;pre&gt;psql -Umyuser -c &amp;quot;lo_export &#039;12345&#039; &#039;myphoto.png&#039; &amp;quot; mydatabase&lt;/pre&gt;
One can also import and export a large object using the equivalent server-side function:
&lt;pre&gt;SELECT lo_import (&#039;/tmp/latestnews.ogg&#039;);&lt;br /&gt; lo_import&lt;br /&gt;-----------&lt;br /&gt;    444611&lt;br /&gt;(1 row)&lt;/pre&gt;Server side functions are restricted in that they can only be
used by the superuser. It can only access files on the machine where
the server is running and the superuser has permission to access (under
normal circumstances this excludes home accounts).

&lt;hr /&gt;

&lt;p&gt;&lt;b&gt;Q:&lt;/b&gt;&lt;i&gt;Isn&#039;t there a way of loading a binary file into a record just like normal data without using Large Objects?&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;As a matter of fact yes. All programming languages such as perl,
tcl, python, php etc, with the necesary hooks into libpq, can insert
data directly using ordinary SQL INSERT commands.
&lt;br /&gt;
Here&#039;s an example using the psql client, with a binary file called &amp;quot;mydocument.pdf&amp;quot;.
&lt;br /&gt;
Create a table called myfiles in a database called temp:
&lt;/p&gt;&lt;pre&gt;CREATE TABLE myfiles(mybinary text);&lt;/pre&gt;
Log into the database:
&lt;pre&gt;psql -Upostgres temp&lt;/pre&gt;
Convert and assign the contents of the binary file to base64, using &amp;quot;openssl&amp;quot;, to the internal variable named &amp;quot;content&amp;quot;:
&lt;pre&gt;set content &#039;&#039;&#039; `openssl base64 -in mydocument.pdf` &#039;&#039;&#039;&lt;/pre&gt;
You can now insert this binary into the table:
&lt;pre&gt;INSERT INTO VALUES myfiles(:content);&lt;/pre&gt;


&lt;hr /&gt;

&lt;p&gt;&lt;b&gt;Q:&lt;/b&gt;&lt;i&gt;How do I carry out an SSL session between client and server?&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;SSL connections are possible only when the capability has been expressly compiled into the client, 
   such as the command line utility psql (using the --with-ssl switch). The postgreSQL server can accept 
   one of three states of encrypted communications: none (no SSL required), dedicated SSL (only SSL sessions are accepted),
   detected (the server attempts SSL session but falls back to none if the client doesn&#039;t have any)
&lt;br /&gt;
The settings in the files pg_hba.conf, postgresql.conf defines the type of socket connection.
&lt;br /&gt;
Insert the following line in the file, postgresql.conf:
&lt;/p&gt;&lt;pre&gt;ssl = true&lt;/pre&gt;
Define the client&#039;s authentication in the file, pg_hba.conf, as for example; 
&lt;pre&gt;#TYPE      DATABASE   USER         IP-ADDRESS    IP-MASK         METHOD &lt;br /&gt; hostssl   ALL        postgres     192.168.0.1   255.255.255.0   password&lt;br /&gt; hostnossl ALL        sraa_client  192.168.0.1   255.255.255.0   password&lt;br /&gt; host      ALL        sraa_admin   192.168.0.1   255.255.255.0   password&lt;/pre&gt;You can define a number of connections with a mix of encrypted
and unencrypted sessions. For example, the first line insists on
encrypted SSL session for the super user logging in from 192.168.2.0.1
while the second line permits the client sraa_client a non encrypted
session coming from the same ip address. The third line tries first an
SSL connection otherwise it switches over to a plain socket connection.


&lt;hr /&gt;

&lt;p&gt;&lt;b&gt;Q:&lt;/b&gt;&lt;i&gt;What if I want an encrypted session and my client doesn&#039;t support it natively?&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;If you are communicating accross a network, you can still have an
encrypted session by running an SSH encrypted tunnel between client and
server. The method is to run &amp;quot;Port Forwarding&amp;quot; between the two
computers. &lt;br /&gt;
In this example, a ssh client is used on the database client side while
the SSH server is resident on the PostgreSQL server side. The client
executes the following command to establish a connection and goes into
the background once a successfull authentication has been made:
&lt;/p&gt;&lt;pre&gt;ssh -fN -L 6262:192.168.2.1:5432 user@192.168.2.1&lt;/pre&gt;
The pg_hba.conf file must be configured to permit login. You must usethe server&#039;s own ip address, 192.168.2.1. 
Here&#039;s an example configuration instruction:
&lt;pre&gt;# IPv4-style local connections:&lt;br /&gt;# TYPE  DATABASE  USER      IP-ADDRESS    IP-MASK     METHOD&lt;br /&gt;  host  all       postgres  192.168.2.1   255.255.255 trust&lt;/pre&gt;
The postgresql.conf file must contain the line:
&lt;pre&gt;tcpip_socket = true&lt;/pre&gt;This example login is made by the psql console client, although
any client would work. It connects to port 6262 on the client
localhost, where it will be forwarded to port 5432 on the remote server
where the PostgreSQL server resides: &lt;pre&gt; psql -U postgres -h 127.0.0.1 -p 6262 template1&lt;br /&gt; &lt;/pre&gt; 


&lt;p&gt;&lt;b&gt;CAVEATS&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;The SSL authentication and connection is not handled by
thePostgreSQL i.e. the server thinks it&#039;s a plain tcp socket
connection, since it&#039;s the SSH session that&#039;s handling the encryption.
&lt;/li&gt;&lt;li&gt;A SSH account is required on the server.
&lt;/li&gt;&lt;li&gt;You can eliminate using passwords by using public-key
cryptography (refer to the SSH man page) Verify that your
authentication will function with port forwarding i.e. start with as
simple authentication as possible such as &amp;quot;trust&amp;quot; and increase it from
there.
&lt;/li&gt;&lt;/ul&gt;


&lt;hr /&gt;

&lt;p&gt;&lt;b&gt;Q:&lt;/b&gt;&lt;i&gt;How do I bind the PostgreSQL server to a particular ip address?&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;There are two ways of assigning the ip address. The first method is to Assign the port number 
to the PGPORT environment variable in the same shell that the server starts up, for example;
&lt;/p&gt;&lt;pre&gt;#!/bin/bash&lt;br /&gt;export PGPORT=6262&lt;br /&gt;pg_ctl -d data start&lt;/pre&gt;
The second method is to edit the postgresql.conf file:
&lt;pre&gt;tcpip_socket = true&lt;br /&gt;port = 6262&lt;/pre&gt;


&lt;hr /&gt;

&lt;p&gt;&lt;b&gt;Q:&lt;/b&gt;&lt;i&gt;I&#039;ve made changes to template1 but now I want to remove them. How do I accomplish this?&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;Every database cluster requires template1. The advantage of adding
objects to template1 is that you can simplify the process of adding
functions, tables, triggers, procedural languages etc to a number of
databases by first adding them first here and then creating these new
databases with the createdb utility or the SQL command CREATE DATABASE.
&lt;br /&gt;
Removing these additions from template1 can be difficult if you don&#039;t remember all the changes.
&lt;br /&gt;There&#039;s two ways creating a clean template1 database. The first
method is to obtain a datadump of template1 before any changes have
been made to it: &lt;/p&gt;&lt;pre&gt;pg_dump -c -Upostgres template1&amp;gt;template1.db&lt;/pre&gt;
You can restore this data defintion back to the database as required:
&lt;pre&gt;psql -Upostgres -f template1.db template1&lt;/pre&gt;
The second method involves creating a new database, using template0 as the TEMPLATE, and 
dumping its data definition to a file. Restore template1 using this newly created datadump 
in a manner similar to what has been outlined in the first example:
&lt;pre&gt;createdb -Upostgres -T template0 replacement&lt;br /&gt;pg_dump -c -Upostgres replacement &amp;gt;template1.db&lt;br /&gt;psql -Upostgres -f template1.db template1&lt;/pre&gt;


&lt;hr /&gt;

&lt;p&gt;&lt;b&gt;Q:&lt;/b&gt;&lt;i&gt;How do I effect changes made in the configuration files without shutting down the server and losing client connections?&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;
Most Unix based distributions include server scripts permitting the
system administrator to run the PostgreSQL server. For example, in a
Debian, Linux, distribution (a System V operating system) we can use:
&lt;/p&gt;&lt;pre&gt;/etc/init.d/postgresql reload&lt;/pre&gt;
Another method is to invoke the PostgreSQL server utility, pg_ctl, directly:
&lt;pre&gt;pg_ctl reload&lt;/pre&gt;Yet a third method is to send a signal to the server process
directly. This can be accomplished by obtaining the process id, where
you can get it by grepping the output from the ps utility, and sending
a SIGHUP signal using the &amp;quot;kill&amp;quot; utility. If the postgres server had a
process number of 13751 , you could reload the configuration files by
typing the following command in a terminal:
&lt;pre&gt;kill -s HUP 13751&lt;/pre&gt;


&lt;hr /&gt;

&lt;p&gt;&lt;b&gt;Q:&lt;/b&gt;&lt;i&gt;How do I determine the size of a table or database?&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;There is an optional module available in the PostgreSQL
&amp;quot;contributions&amp;quot; section that will return the size of any relation in a
database, or even the database itself. Look in your postgres library
directory for a file named &amp;quot;dbsize.so&amp;quot; to see if you have the module,
otherwise you will need to download the complete PostgreSQL source,
including the contributions source, and compile it yourself. &lt;br /&gt;
If the module is present you will need to create two functions, called
&amp;quot;database_size&amp;quot; and &amp;quot;relation_size&amp;quot;, to your database before you can
use it. Carry out the following SQL commands in the database you are
currently logged into (note: these functions will only work in the
database where the following SQL commands have been invoked):
&lt;/p&gt;&lt;pre&gt;CREATE FUNCTION database_size (name) RETURNS bigint&lt;br /&gt;    AS &#039;$libdir/dbsize&#039;, &#039;database_size&#039;&lt;br /&gt;    LANGUAGE C WITH (isstrict);&lt;br /&gt;&lt;br /&gt;CREATE FUNCTION relation_size (text) RETURNS bigint&lt;br /&gt;    AS &#039;$libdir/dbsize&#039;, &#039;relation_size&#039;&lt;br /&gt;    LANGUAGE C WITH (isstrict);&lt;/pre&gt;
Here is an example invocation that returns the size of the database &amp;quot;template1&amp;quot;:
&lt;pre&gt;SELECT database_size(&#039;template1&#039;);&lt;/pre&gt;
Here is an example invocation that returns the size of the table &amp;quot;myrelation&amp;quot; in the currently logged in database:
&lt;pre&gt;SELECT relation_size(&#039;myrelation&#039;);&lt;/pre&gt;


&lt;div id=&quot;google-toolbar-tooltip&quot; style=&quot;border: 1px outset rgb(0, 0, 0); padding: 2px; background: rgb(255, 255, 221) none repeat scroll 0% 50%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; font-family: serif; font-style: normal; font-variant: normal; font-weight: normal; font-size: medium; line-height: normal; font-size-adjust: none; font-stretch: normal; position: absolute; color: rgb(17, 17, 17); text-align: left; text-decoration: none; text-indent: 0pt; text-transform: none; z-index: 2147483647; left: 674px; top: 136px; display: none;&quot;&gt;&lt;center&gt;&lt;small&gt;DISTINCT: 另外的; 不同的; 明瞭的; 清楚的; 明顯的; 顯著的; 不同; 楚; 獨特; 較; 明顯; 清; 清楚&lt;/small&gt;&lt;/center&gt;&lt;/div&gt; 
</content> 
</entry> 
 
</feed>