标签:mysql

浏览模式: 标准 | 列表 | 图文
PDF下载:《High Performance MySQL》

PDF下载:《High Performance MySQL》

回忆未来的张宴推荐了这本书,并且在他的博客上提供了下载的链接,链接是新浪的爱问:点此下载《High Performance MySQL Second Edition》PDF电子版,并且博客上还有详细介绍:

XML/HTML代码

High Performance MySQL Second Edition
作者: Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy Zawodny / Arjen Lentz / Derek Balling

副标题: Optimization, Backups, Replication, and More
ISBN: 9780596101718
页数: 708
定价: USD 49.99
出版社: O'Reilly Media, Inc.
装帧: Paperback
出版年: 2008-06-18

High Performance MySQL is the definitive guide to building fast, reliable systems with MySQL. Written by noted experts with years of real-world experience building very large systems, this book covers every aspect of MySQL performance in detail, and focuses on robustness, security, and data integrity.

High Performance MySQL teaches you advanced techniques in depth so you can bring out MySQL's full power. Learn how to design schemas, indexes, queries and advanced MySQL features for maximum performance, and get detailed guidance for tuning your MySQL server, operating system, and hardware to their fullest potential. You'll also learn practical, safe, high-performance ways to scale your applications with replication, load balancing, high availability, and failover.

This second edition is completely revised and greatly expanded, with deeper coverage in all areas. Major additions include:
* Emphasis throughout on both performance and reliability
* Thorough coverage of storage engines, including in-depth tuning and optimizations for the InnoDB storage engine
* Effects of new features in MySQL 5.0 and 5.1, including stored procedures, partitioned databases, triggers, and views
* A detailed discussion on how to build very large, highly scalable systems with MySQL
* New options for backups and replication
* Optimization of advanced querying features, such as full-text searches
* Four new appendices
The book also includes chapters on benchmarking, profiling, backups, security, and tools and techniques to help you measure, monitor, and manage your MySQL installations.

为此,张宴还提供了一张图片:

cdfe04098a38c45b1bf960361f2dfa60

整篇博客我作了一下整理和排序,想看原文的,请到:http://blog.s135.com/read.php?381,因为在这个页面上张宴采用了划词翻译,如果有看不懂英文的话,选中一下就会自动翻译了。。我没有提供。也不想再插入一些代码。呵呵

为了方便大家,我也上传了这个文件,大家可以点击下载:df71d0e5017d126df2038ad084433c8d


MySQL之表结构修改[转]

MySQL之表结构修改[转]

Author:丹臣 posted on Taobao.com

mysql数据库里,对一个已创建的表进行DDL操作,比如说添加一个字段。在做测试时,发现ddl操作的时间特别的长。oracle里,通常情况下只是 修改数据字典就可以了,操作时间非常的短,阻塞DML的时间也比较短。mysql数据库对表进行ddl操作跟oracle数据库有很大的不同,它先要把原 表拷贝一份到临时表,这期间不阻塞select,阻塞所有的更改操作(update,delete,insert),对临时表ddl操作完成,删除原表, 重命名临时表。
如果一张比较大的表进行ddl变更,比如说40G,那拷贝的时间让人无法忍受,并且阻塞所有的DML操作,让业务无法继续。

以下是测试过程:

mysql> desc t1;
+-------------------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+------------------+------+-----+---------+-------+
| id | int(11) | YES | MUL | NULL | |
| nick | varchar(32) | YES | | NULL | |
| email | varchar(32) | YES | | NULL | |
| gmt_create | datetime | YES | | NULL | |
| gmt_modified | datetime | YES | | NULL | |
+-------------------+------------------+------+-----+---------+-------+
mysql> select count(*) from t1;
+----------+
| count(*) |
+----------+
| 2228017 |
+----------+
1 row in set (1.78 sec)

现在对它进行表结构变更,增加一列:

mysql> alter table t1 add(tel varchar(20));
Query OK, 2304923 rows affected (41.03 sec)
Records: 2304923 Duplicates: 0 Warnings: 0

在上述表结构变更过程中,启动另外一个会话,进行select查询操作和一个更新操作:

mysql> select count(*) from t1;
+---------------+
| count(*) |
+---------------+
| 2304923 |
+---------------+
1 row in set (2.10 sec)

mysql> select * from t1 limit 10;
+------+-------+------------------------+----------------------------+----------------------------+
| id | nick | email | gmt_create | gmt_modified |
+------+-------+------------------------+----------------------------+----------------------------+
| 0 | nick0 | nick0@taobao.com | 2008-03-14 00:00:00 | 2008-03-14 00:00:00 |
| 1 | nick1 | nick1@taobao.com | 2008-03-14 00:00:00 | 2008-03-14 00:00:00 |
| 2 | nick2 | nick2@taobao.com | 2008-03-14 00:00:00 | 2008-03-14 00:00:00 |
| 3 | nick3 | nick3@taobao.com | 2008-03-14 00:00:00 | 2008-03-14 00:00:00 |
| 4 | nick4 | nick4@taobao.com | 2008-03-14 00:00:00 | 2008-03-14 00:00:00 |
| 5 | nick5 | nick5@taobao.com | 2008-03-14 00:00:00 | 2008-03-14 00:00:00 |
| 6 | nick6 | nick6@taobao.com | 2008-03-14 00:00:00 | 2008-03-14 00:00:00 |
| 7 | nick7 | nick7@taobao.com | 2008-03-14 00:00:00 | 2008-03-14 00:00:00 |
| 8 | nick8 | nick8@taobao.com | 2008-03-14 00:00:00 | 2008-03-14 00:00:00 |
| 9 | nick9 | nick9@taobao.com | 2008-03-14 00:00:00 | 2008-03-14 00:00:00 |
+------+-------+------------------------+----------------------------+----------------------------+
10 rows in set (0.00 sec)

mysql> update t1 set nick='test_nick' where id=1;
Query OK, 4 rows affected (43.89 sec) --这里是阻塞的时间
Rows matched: 4 Changed: 4 Warnings: 0

通过以上实验可以看出,对表进行ddl操作时,mysql并不阻塞select查询,但会严重阻塞dml操作。另外,如果你要对表进行ddl操作,由于有一个拷贝操作,你要计算好你的可用空间够不够?如果你的系统经常要进行表结构变更,那么你将不得不要考虑此问题!

--EOF--

膘叔:说实话,一般对于表的操作往往都是在夜深人静的时候,虽然select并不影响,但为避免在更新表结构的时候更新数据,这还是必须的。。。以防万一啊

MySQL主从服务器的一些技巧

MySQL主从服务器的一些技巧

问题:主从服务器表类型的选择

一般的共识是主服务器使用innodb,从服务器使用myisam,以便各尽其能。

问题:主从服务器字段类型的选择

字段类型对于分页等操作有很大影响。主服务器一般是innodb,因为不涉及查询,所以可以使用varchar等来存储字符串来节省空间,从服务器一般是 myisam,因为涉及查询,所以必须在char和varchar之间仔细权衡,没有varchar, text, blob字段的表是静态表,反之是动态表,静态表的检索效率要比动态表好若干倍,一般来说,所有涉及大结果集的查询都应该尽可能保证在静态表上完成,这里 说一个例子:比如说常见的articles表有title(varchar), body(text)等字段,在做文章列表的时候,因为不是静态表,所以查询不会很快,下面开始重构解决方案:把原来的articles表拆分成 subjects表和contents表,title字段设置为一个足够的char类型放在subjects表里,body字段还保持是text类型放到 contents表里,subjects和contents表之间的关系是一对多,这样,顺带着也方便的实现了多页文章的功能,而且更重要的是在查询文章 列表的时候,操作都是在subjects静态表里完成,效率肯定会比前一种方案提升很多。

问题:主从服务器NOW()函数造成数据不一致

假设在主服务器上执行一条INSERT .... VALUES ( ..., NOW()),那么在从服务器上也会同样执行一条的SQL语句,但是一来主从服务器各自的时间设置可能就不一致,二来主从服务器间的SQL同步也可能存在 时间上的的延迟,这样,NOW()在两台服务器上的结果就可能不一致。解决方法是显而易见的,就是不要使用NOW(),时间的计算在应用程序里完成。这里 介绍一个额外的小技巧:在PHP里如果想获得当前时间的时间戳,不要用time(),而应该使用$_SERVER[‘REQUEST_TIME’] (PHP版本大于5.1有效),这样少做了一次系统调用,更有效率。

问题:主从服务器读写分离时读操作失败

先重现一下问题:比如说添加一条新数据,添加成功后根据last_insert_id跳转到新添加数据的浏览页面。在此过程中添加新数据的操作是在主服务 器上完成的,浏览新数据的操作实在从服务器上完成的,不过由于主从服务器间SQL同步存在延迟,所以当使用last_insert_id在从服务器上查询 的时候,从服务器很可能还没有还没来得及同步到此记录,所以读操作失败。解决思路也不复杂,在代码里加入一个缓存层(可以使用memcached),新添 加的数据都顺手放到缓存层里一份,新数据的读操作也先查询缓存层,这样就不会再有读操作失败的问题了,当然删除或者更新数据的时候也要顺带着处理好缓存数 据,可以使用观察者模式来搞定。不过这样缓存方案只限于读取单一的记录,对于读取列表的记录的情况,则是无效的。

问题:主从服务器索引是否有必要保持一致

一般都是利用主从服务器完成读写分离,从服务器上进行读操作,主服务器进行写操作,这样的话,主服务器上仅保留主键,外键,唯一索引等必要的索引即可,以 便保持数据合法性,而对于那些原本用于优化SELECT操作的索引,可以全部删除,如此的话主服务器的写操作效率会提升很多。

作者:老王
原文:http://hi.baidu.com/thinkinginlamp/blog/item/5d72dd5469b1885fd0090633.html

walker早期文章:通过MySQL内置全文检索实现中文的相关检索

walker早期文章:通过MySQL内置全文检索实现中文的相关检索

一直在搜索这块有问题,中文搜索的话,不可避免的会遇到搜索 A 的时候会出现 B 结果的情形,这种情况在MYSQL4.0的时候犹为明显,最近在翻代码的时候,翻到walker以前写的一篇文章,依稀记得大概也是05年左右的事情了吧。

05年这家伙写了不少代码,什么BMP识别啥的。如今也都随着服务器的损坏而烟消云散了。借着google的光,把walker这篇以前的文章再COPY回来。为以后也开发可以做个参考,只是它的这个方法太占数据库空间了。呵呵

如今的walker代码是几乎不写了,以wow为主,可怜的人啊。。。。。http://www.walkerlee.net 是他现在的网站。

文章如下:
/**
* @author : walkerlee
* @copyright : www.neatstudio.com | www.walkerlee.net
*/

转载请保留以上信息。

关键字:MySQL 全文检索 全文索引 中文分词 二元分词 区位码 相似度

注:本文使用的MySQL版本为:MySQL 4.0.x

在MySQL4中,是已经开始支持全文检索(索引)的了。但是只是对英文支持全文检索。
由于英文在书写上的特殊性,使得分词算法相对中文来说,简单得多。一般来说,我们可以通过单词与单词之间的空格,以及标点符号来完成这个分词过程。
但是就中文来说,就没有那么简单。MySQL无法对中文做出正确的分词,假设有如下英文句子:

"Hello world! Hello PHP! "

通过上面提及的方法,可以很简单的把这个句子分词为:

1 Hello
2 world
3 PHP

我们再来看看中文的句子:

"你好世界,你好PHP! "

按照英文的算法,分词如下:

1 你好世界
2 你好PHP

显然是不能满足我们的需要的。

所以,首先我们要做的是,把中文的句子转变为MySQL眼中的英文,以便使得它能以英文分词算法去对句子进行正确的分词处理。
先将上面中文句子进行标点过滤处理,得到以下句子:

你好世界 你好PHP

接着再使用中文分词中较简单实现的二元分词算法对句子进行二元分词,得到以下句子:

你好 好世 世界 你好 PHP

因为把标点符号替换为空格,以及PHP本身为英文字母的关系,可以不用进行二元切分,所以得到上面句子。
这个时候,我们来看看处理过后的句子,会发现,就其书写格式上来说,已经符合英文的书写格式,既以空格,标点来对单词形成自然间隔。只是上面句子没有标点,只有空格而已。
到此,我们已经成功的将中文“翻译”为MySQL能理解的“英文”书写格式。

但是,问题还没解决,首先,MySQL中,ft_min_word_len(分词词汇最小长度)这个参数的默认值为4,也就是4个字母以上长度的单词,才会被考虑,小于4个的,将会被忽略。
如果不改变这个长度,按照上面的分词结果,我们将无法通过 你好,世界,PHP等检索到相关的结果,因为分出来的词太短了,不在MySQL的选择范围内。
我们可以通过修改ft_min_word_len的值,将其设置为2来解决上面问题,但是这样做的话,在检索列表中的原本就为英文的短小词汇,如:PHP,MP3,也会被划入检索范围内,这样做的结果是,出现很多无意义的相关结果。

请看以下列表:

[MP3] the look
[MP3] because of you

因为他们都同有MP3在标题中,所以会出现上述提到的问题。

回到ft_min_word_len值的问题,我们之所以要修改他,是为了能让MySQL找到我们的二元分词,但是短小的英文又被“无辜”的卷入,我们目 前要解决的问题就是,如何使得MySQL能检索到二个字的中文词汇,又能忽略掉原本的英数?第一个反应是把中文MD5,这样以上分词就将转化为以下结果:

你好 好世 世界 你好 PHP => b94ae3c6d892b29cf48d9bea819b27b9 f5625345be46432fb0fd51340fcf6679 9067de5206278a93823f9c5dc2c737fd b94ae3c6d892b29cf48d9bea819b27b9 PHP

这样做,首先是使得中文分词的长度超越了默认的2个字,同时消除了中文的歧义性。(MySQL4对中文的处理有问题),搜索“车轮”时候,不再会出现类似“发动机”结果的问题。(车轮的例子只是为了方便理解而做出的假设)

通过上面的做法,已经解决了分词最小长度的问题,顺利的把中文词汇长度升级,从而达到把中文词汇划入检索范围,把较短的英数划出检索范围。
休息一下,然后发现这个MD5后的字符串是否太长了点……比较占用空间,要不,于是想到区位码,4位数的区位码能表示一个GB汉字,一个词有二个汉字组成,转换为区位码后是8个数字。不但能确定惟一性,也就MD5而已减少了长度。下面是转换后的:

你好 好世 世界 你好 PHP => b94ae3c6d892b29cf48d9bea819b27b9 f5625345be46432fb0fd51340fcf6679 9067de5206278a93823f9c5dc2c737fd b94ae3c6d892b29cf48d9bea819b27b9 PHP => 36672635 26354232 42322971 36672635 PHP

呵呵,是不是比MD5的小了很多呢?最后我们把相同的词汇留一个,多余的删除。得到

36672635 26354232 42322971 PHP

于是就完成了 "你好世界,你好PHP! " 到 "36672635 26354232 42322971 PHP " 的转换。

通过上面方法结合MySQL全文检索语句,我们可以通过给出一个标题例如: "迈克尔·杰克逊 -《危险之旅之布加勒斯特站》 "找出类似以下的相关标题

迈克尔杰克逊 -《迈克尔杰克逊危险布加勒斯特演唱会》
Michael Jackson -《迈克尔杰克逊 罗马尼亚 危险演唱会》
迈克尔杰克Michael Jackson -《危险之旅》
迈克尔杰克逊 -《迈克尔杰克逊 美国50annive演唱会危险片段》
迈克尔杰克逊 -《迈克尔杰克逊 终极收藏 原版DVD危险演唱会》
迈克尔杰克逊 杰克逊五兄弟 -《The Jackson Motown 25 演唱会》
迈克尔杰克逊 -《迈克尔杰克逊BAD日本Yokohama演唱会》
迈克尔杰克逊 -《迈克尔杰克逊日本大阪演唱会》
迈克尔杰克逊 -《迈克尔杰克逊之胜利-达拉丝演唱会》
迈克尔杰克逊 -《迈克尔杰克逊之胜利演唱会 比丽珍 片段》
迈克尔杰克逊 -《迈克尔杰克逊德国危险演唱会之 billie jean片段》
迈克尔杰克逊 -《Michael Jackson -30周年演唱会》
Michael Jackson -《迈克尔杰克逊 马尼拉 历史演唱会》
迈克尔杰克逊 -《1993年美国橄榄球中场休息精彩表演》

表结构 article
title varchar 200 -------- 用于存放标题 (显示用)
ft text ---- fulltext 用于存放标题分词结果 (检索用)

首先我们在把标题保存到数据库时候,就已经对标题进行分词转区位码,保存到ft字段中,用于相关性的检索。
然后把给出的标题 "迈克尔·杰克逊 -《危险之旅之布加勒斯特站》 "转为 "34853143 31432291 22910104 01042960 29603143 31434923 46034753 47535414 54143435 34355414 54141828 18282851 28513253 32534325 43254456 44565330 ",最后进行全文检索查询:

SELECT title, MATCH( ft ) AGAINST( '34853143 31432291 22910104 01042960 29603143 31434923 46034753 47535414 54143435 34355414 54141828 18282851 28513253 32534325 43254456 44565330 ' IN BOOLEAN MODE ) AS score
FROM article
WHERE MATCH( ft ) AGAINST( '34853143 31432291 22910104 01042960 29603143 31434923 46034753 47535414 54143435 34355414 54141828 18282851 28513253 32534325 43254456 44565330 ' IN BOOLEAN MODE )
ORDER BY score DESC
LIMIT 0, 5

从SQL Query上来看,进行了两次全文检索,其实不然,MySQL会将其视为一次,所以不比担心。
同时使用了AS score,这个score是相似度,分值越高,自然越与给出的标题相近。

二点建议:
1.在实际使用中,挑选score大于1的作为检索结果。
2.检索结果会将本身标题也算入其中,根据score排序,为第一条,别忘记过滤哦 ^_^。

站在用户的立场来说,我们给用户提供了更多的相关内容,站在搜索引擎立场上来说,给关键字提供了更多的相关链接,形成了良好的站内互联结构,提高了搜索引擎对网页的评价。

如果各位碰到错误的不合理的地方,恳请指正,共同进步。谢谢!

参考资料:

1.Monkey的二元分词 作者:Monkey http://www.baidu.com/s?wd=monkey+%B6%FE%D4%AA%B7%D6%B4%CA&cl=3
2.PHP里如何实现汉字转区位码 提供者:haoyoul http://zhidao.baidu.com/question/5371961.html
3.对dvbbs.php全文搜索的完全分析 作者:fcicq http://www.phpx.com/happy/viewthread.php?tid=124691

MYSQL官方的文章:几种无限分类的算法……

MYSQL官方的文章:几种无限分类的算法……

我只贴一种,其余的去看:http://dev.mysql.com/tech-resources/articles/hierarchical-data.html

The Adjacency List Model

Typically the example categories shown above will be stored in a table like the following (I'm including full CREATE and INSERT statements so you can follow along):

CREATE TABLE category(
category_id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(20) NOT NULL,
parent INT DEFAULT NULL);


INSERT INTO category
VALUES(1,'ELECTRONICS',NULL),(2,'TELEVISIONS',1),(3,'TUBE',2),
(4,'LCD',2),(5,'PLASMA',2),(6,'PORTABLE ELECTRONICS',1),
(7,'MP3 PLAYERS',6),(8,'FLASH',7),
(9,'CD PLAYERS',6),(10,'2 WAY RADIOS',6);

SELECT * FROM category ORDER BY category_id;

+-------------+----------------------+--------+
| category_id | name | parent |
+-------------+----------------------+--------+
| 1 | ELECTRONICS | NULL |
| 2 | TELEVISIONS | 1 |
| 3 | TUBE | 2 |
| 4 | LCD | 2 |
| 5 | PLASMA | 2 |
| 6 | PORTABLE ELECTRONICS | 1 |
| 7 | MP3 PLAYERS | 6 |
| 8 | FLASH | 7 |
| 9 | CD PLAYERS | 6 |
| 10 | 2 WAY RADIOS | 6 |
+-------------+----------------------+--------+
10 rows in set (0.00 sec)

In the adjacency list model, each item in the table contains a pointer to its parent. The topmost element, in this case electronics, has a NULL value for its parent. The adjacency list model has the advantage of being quite simple, it is easy to see that FLASH is a child of mp3 players, which is a child of portable electronics, which is a child of electronics. While the adjacency list model can be dealt with fairly easily in client-side code, working with the model can be more problematic in pure SQL.

Retrieving a Full Tree

The first common task when dealing with hierarchical data is the display of the entire tree, usually with some form of indentation. The most common way of doing this is in pure SQL is through the use of a self-join:

SELECT t1.name AS lev1, t2.name as lev2, t3.name as lev3, t4.name as lev4
FROM category AS t1
LEFT JOIN category AS t2 ON t2.parent = t1.category_id
LEFT JOIN category AS t3 ON t3.parent = t2.category_id
LEFT JOIN category AS t4 ON t4.parent = t3.category_id
WHERE t1.name = 'ELECTRONICS';

+-------------+----------------------+--------------+-------+
| lev1 | lev2 | lev3 | lev4 |
+-------------+----------------------+--------------+-------+
| ELECTRONICS | TELEVISIONS | TUBE | NULL |
| ELECTRONICS | TELEVISIONS | LCD | NULL |
| ELECTRONICS | TELEVISIONS | PLASMA | NULL |
| ELECTRONICS | PORTABLE ELECTRONICS | MP3 PLAYERS | FLASH |
| ELECTRONICS | PORTABLE ELECTRONICS | CD PLAYERS | NULL |
| ELECTRONICS | PORTABLE ELECTRONICS | 2 WAY RADIOS | NULL |
+-------------+----------------------+--------------+-------+
6 rows in set (0.00 sec)

精通MYSQL数据库——连载十二

三大范式:第一范式,第二范式,第三范式,听着名字就很恐怖。但其实现在的人都被这个所谓的第三范式折腾死了,有事没事就拿出来涮涮,究竟怎么理解这些呢?一个一个慢慢的介绍。

数据库理论家们为数据库的设计1对N,N对N这种问题总结出了一个通用的解决方案,只需一步一步地三个范式(Normal Form)的规则应用到自己的数据库上就可以了。

第一范式的规则:

1、内容相似的数据必须“消除”(所谓消除,即再创建一个表来存储他们)

2、必须为每一组相关数组分别创建一个数据表

3、每条数据记录必须用一个主键来标识

第一条规则,看上去就比较适用于1对多的情况

第二条规则就不太好控制了,很多人认为第二条规则很难理解,数据的相关度,很难简单的描述清楚

第三条规则其实是一个实践经验,它的意思是数据表里的第一个数据行都应该包括一个独一无二的标识符作为索引。在使用MYSQL的时候,我们大多采用了自增字段来作为主键,但并非只有整数的自增字段才能作为索引,只要是独一无二的数据列,都可以用来做索引,之所以采用自增列,那是因为:1、不需要主动插入值2、整数列的时间和空间效率相对比其他类型的要高。

第二范式的规则:

1、只要数据列里的内容出现重复,就意味着应该把数据表拆分为多个子表

2、拆分形成的数据表必须用外键关联起来

第二范式,其实是在第一范式的基础上再进行一个拆分。指的就是第一范式规则的第二条内容。

外键关系在第二范式里显得特别重要,是因为第二范式时,数据会拆得更细,如果没有外键关联,恐怕数据就找不回来了。外键相当于我们日常所说的:交叉引用,对开发人员来说相当于指针。

第三范式的规则

第三范式只有一条规则:与主键没有直接关系的数据列必须“消除”

其实也就是把第二范式再分解,再建表。

可想而知,等到真正把一堆数据完全按照第三范式来进行设计的时候,恐怕在数据库里也就只能看到一堆ID了,数据呢?数据在哪里?通过外键,外键的外键,外键的外键的外键来慢慢的一个一个搜索吧。

对于MYSQL 4.1以下的版本,第三范式是会要了他们的命的,foreign key功能的不完善,让MYSQL 4.1以下版本,基本不适合第三范式,能用到第二范式设计时,数据表的效率已经几乎不能保证了。

这三个范式是著名学者E.F.Codd最先提出来的,后人在此基础 上对大到数学集合理论、小到关系数据库设计细节等诸多方面进行了研究和探索。如果对这方面有兴趣的朋友,还是多找找相关的书籍看看为好。

如果你的性子比较急,那么你可以尝试按照下面的方法来进行:

1、设计数据库的时候,一定要给自己充足的时间,如果等到数据库充满了数据,而程序也几乎开发完毕时,才发现数据库设计有缺陷,那么花费的代价就太大了

2、如果发现自己创建的表的数据列有序号,如name1,name2等,那一般就意味着还有更好的解决方案没有采用。可以考虑多创建一个表,而把这些分拆开。

3、第一时间往数据库里多插点测试数据,如果发现冗余量很大,往往就是表需要分拆的信号

4、设计时应该注意数据与数据之间的关联及引用关系

5、对于设计完的数据库,应该自己尝试写SQL语句,看看能否达到你预想的目标,如果达不到,那就要考虑是否设计的有问题。

6、如果你还是等不急,根据你的需要,到网上找找有没有类似的示例数据库,可以考虑拿来作借鉴。

说了这么多时间的范式,最后再说说他们的优缺点吧

缺点:数据表的个数越多,也就相对证明了从表单里获取数据并往表里插的时候,复杂性非常大,给开发人员会带来很大的困扰。同样,表多了,查询结果时,从中提取相关数据生成查询结果的复杂性也就越大;数据库的容量随着表的拆分量的增大而增大(不过现在也不是什么矛盾了,硬盘的价格几乎也快到了白菜价了,这点可以被忽略)

优点:严格按照范式设计出来的数据库,能够提供最丰富、最灵活的查询选项,人们往往都是在等到必须使用一种新的查询或者必须对数据进行一种新的分类时才会真正意识到这一点,但可惜的是,这些新需求往往都是出现在数据库已投入运行数月之后,到时候再改数据库,代价非常大。


现在工作有点忙,连载不会忘记,但更新频率会放慢,毕竟全部都是手工打出来的字。

不会象写小说那样太监掉的,毕竟这个东西对我自己来说,也是一种学习

给自己加油,为自己打气。也谢谢大家的支持

杂谈二

杂谈二

博客本来就是用来记录内心想法的东西,只是我的博客可能记录的技术类的东西相对较多,国庆期间嘛,心思也不在技术上,于是就有了杂谈。

美国众议院、参议院终于同意了救市方案,7000亿美金,听起来很恐怖,可惜股市还是下跌了,恐怕华尔街那些人就非常开心了,压力会小一点了。我在上篇杂谈里就说过,不希望会有这种事情发生,毕竟有第一次也就会有第二次。布什在促进这件事成功,是因为不想留下污点?个人认为。两个竞选者促进成功,是因为这样可以在上台后压力小一点,反正用的钱又不是我的,也不是我下令的,责任不在我身上。可惜对于美国这种物权法很看中的国家来说,民众是怎么想的?7000亿,要纳多少税?在用自己的钱救市,心里是迷惘多一点还是期盼多一点?我交出去的钱,终于派上用场了?可惜,华尔街人应该也在想,怕啥,再怎么样,还是会有人帮我的。。。

除开经济,恐怕搞技术的人这两天都在关注着GOOGLE推出的在线备份MYSQL的innodb数据库?这里提到了,这里也提到了,其实讲的都是GOOLE CODE上的内容,谁来做小白鼠?短时间内谁敢用?估计还是要过段时间了,不过,这毕竟是一个想法,以后这种类似的东西会越来越多的吧?

再说说软件,思维导图,应该算是最近一段时间比较流行的东西了,思维导图是国内人员的翻译,详细介绍如下:


MindManager是一个创造、管理和交流思想的通用标准,其可视化的绘图软件有着直观、友好的用户界面和丰富的功能,这将帮助您有序地组织您的思维、资源和项目进程。

MindManager也是一个易于使用的项目管理软件,能很好提高项目组的工作效率和小组成员之间的协作性。它作为一个组织资源和管理项目的方法,可从脑图的核心分枝派生出各种关联的想法和信息。
MindManager可以使讨论和计划的过程从根本上发生变化,促进实现你的思想和方案。
在一般的传统的讨论中至少包含四个步骤:
1、从图表或白板上获得思想
2、转录成为很难阅读的电子版
3、在组织信息资料的过程中不可避免的要损失某些思想的重要关系
4、通过印刷品或者电子邮件分发资料
时间和资源在重复的信息中被浪费了,同事们很难理解会议的结果。
但是,MindManager软件改变了研讨过程,只通过以下两个步骤就可以在同一页中显示出每个人的观点,从而避免了不必要的重复性的工作。
1、迅速的以可视化形式获取和组织思想,促进团队内的协作和个体积极性。
2、能够直接分发会议记录,比以往更快的落实各种设想。
点击“输出”(export),可以得到PDF、Word、Powerpoint、HTML和图片格式文件。
cnbeta上面有详细介绍,上面的也是COPY而来,地址为:http://www.cnbeta.com/articles/66193.htm,除了这个软件,另外这五款软件也是不错的,值得下载使用,我没有用过,但是看名称和介绍,就知道应该是值得用用:5个最出色必须拥有的windows xp 管理插件
精通MYSQL数据库——连载十一

精通MYSQL数据库——连载十一

一个好的数据库设计应该符合以下几点要求:
1、数据表里没有重复冗余的数据(如果总是往里面插入同样的数据,那应该是设计上有问题,当然现在在利用空间换时间的时候,多数人还是保留了这样的想法)
2、数据表里没有column1,column2,column3……这类没有明确意义的字段,因为这样会让后来人摸不清头脑
3、数据表占用的空间越小越好
4、使用频率高的数据表的查询,应该都能以简单高效的方式执行(表内数据少的时候,你就是10几个left join,你可能都感觉不出什么,但数据量一大,你一个left join都会让你感觉到速度慢下来,如果最初设计时没有满足这个要求,那么,以后想改可能也没有机会了)
这些也只是一些总的原则,也只是简单的介绍,以后会详细说明,当然上面这几点并非完全正确,就象第三范式,这是一个标准,但这个标准真的就是最好的吗?并非如此,但我们现在是在讲设计数据库,它好不好,目前不讲。以后一起讨论

为MYSQL的数据库和数据表甚至字段起名字还是有讲究的,最重要的是,千万不要使用保留关键字,而且有一些单词很奇怪,在4.0里面并不是关键字,但升级后,却变成了关键字。
详细的关键字列表请看:MYSQL手册中保留字部分
对于一个完整的设计应该注意以下几项:
1、由于MYSQL对数据列的命名不区分大小写,而对库名和表名区分大小写,因此为了规范和统一,请使用同样的规则,不要象程序代码那样来个骆驼命名啥的,这样只会给开发带来困难,建议是全部采用小写,移植、升级都方便
2、不要采用特殊字符或者中文,MYSQL对于多字节的处理并不十分完美,虽然支持中文建库、建表等,但实在不建议使用,如果你的服务器对中文支持不好,可能建库的时候就会是乱码,字段里,明明看到有值就是查不出,所以,为了规范,还是采用英文,26个字母的排列组合,没有那么复杂的。
3、数据库、表、字段的长度请不要超过64个字符,
4、表名和数据列名,请尽量采用有意义的名称,不要出现上文提到的那种column1,colnmn2之类的,时间长了,你自己都可能不知道是什么意思
5、给字段命名,需要有规范,因为这样会减少粗心带来的错误,比如username,user_name,如果分在各个表里,恐怕你每次写程序的时候,都得再检查一遍吧?对于由多个单词组成的字段,要么全部加下划线,要么全部不加,这样也比较有利于开发和维护
6、数据列的单复数,原因和5一样,要么全部单数,要么全部复数,一会单数一会复数的,开发和维护的时候,你就得盯着数据表来进行了。

数据库的设计是一件很复杂的事情,要在短时间内把一批数据分割开,并存储到数据库中,还得为开发人员提供足够的优化空间,不是一天两天就能完成的,当然现在有很多这样的工具,比如powerdesign(PD),在设计完后,还能导出数据库,确实是挺方便,但这样的软件,价格就太高了,不是我们所买得起的。
平时,我们还是使用WPS的电子表格,或者openoffice的电子表格功能,设计好数据表(电子表格最大的好处就是有几乎无穷的sheet,可以让你把一个很大的库放在这些sheet里),而且,几乎每台电脑上都会有这样的工具,便于交流。这样可以在最初的阶段对于一些数据列进行安排(没办法建立索引的,只是简单的用来布局,检查设计上是否有缺陷)

对于管理MYSQL,也有很多工具,比较常见的,就是:phpMyadmin;MYSQL自已也提供过,好象是mysqlFront?记不太清,现在我自己用的是navicat for mysql lite ,不用钱的东西都是好的。虽然在国内,大家都了解软件业的行情。自己也处于软件业的下游,能够使用正版,还是使用一下正版吧。不能使用正版的,找找免费版。
在我看的书上,它介绍说openoffice里其实还隐藏着连接数据库这个功能的,而且可以能够象创建视图一样来创建SQL,这个功能不错,我以后要好好看看,如果确实有用,那我WPS也不装了,直接使用openoffice。
不过,最常用的,最方便的,还是使用phpmyadmin,它实在是居家旅行、杀人灭口之大杀器。

精通MYSQL数据库——连载十

本来觉得二进制字段没有什么好介绍的,本来嘛,二进制字段,不就是xxxtext变成了xxxblob?长度,大小都没有变化,只是存储的类型变成了二进制,如果把那些xxxtext字段的属性加一个binary,那就和xxxblob差不多了。
只是在没有加上binary属性的时候,xxxText字段的排序和比较是按字符串类型处理,而xxxBlob是按二进制处理的。加了BINARY属性自然是一样的。
关于在数据库里存在BLOB信息,历来就是一个有争议的话题。最早的VBB论坛就是把附件存在数据库里的,后来还有人单独做HACK把附件剥出来。很多人认为数据库就应该存储一些文本信息,对于二进制数据(图像、附件等)就只应该存储链接,而把文件单独存储出去。这样可以更加有效的利用数据库的空间。
但支持把附件存储在数据库的人却认为,二进制数据存储在数据库内,有利于数据的迁移、备份,提高了数据的集成程度,而且在程序里也能够使用统一的形式访问数据。把常用的数据和这些二进制数据存储在同一个表内,一般被DBA们所痛恨,因为这会导致所有的数据记录的存取速度变慢,而且BLOB数据在正常操作情况下只能作为一个整体来读出。也就是说如果一个BLOB数据长度是1024KB,如果你仅仅想读最后那24KB的内容,没有直接的办法,只能先读出来,然后再定位到最后,BLOB数据只能以一个整体来读写和传输。
从5.0.3开始,原来的BIT型字段正式变形,成为二进制字段了,它的最大宽度达到了64,为了这个BIT型字段,MYSQL还特地增加了一条用来写出二进制数据的新语法:b'0101',SELECT查询的时候,遇到BIT型,将返回二进制数据。(我没有5.0.3的版本,没有测试过怎么读取,书上介绍,可以先使用 seelct bit_field + 0 命令把二进制转为整数,再使用select bin(bit_field + 0 ) 将这些整数显示为二进制)
对于二进制来说,数据会有溢出现象,它分为上溢出和下溢出,但不管是如何的溢出,只要是溢出了,所有的二进制位都将被设置为1。例如将-1,0,1,7,8五个数字依次存入BIT(3)数据列的时候,实际存放的是b'111',b'000',b'001',b'111',b'111'。
除开这些二进制字段,剩下的就是具有MYSQL特色的字段了,如果没有什么必要,确实不太建议使用,因为其他的数据库都不支持这两种类型,一旦在数据迁移的时候,很有可能会造成丢失或增大工作量,是什么字段呢?他们就是ENUM和SET(枚举和集合)。
对于MYSQL来说,这两种字段对于涉及字符的操作,有很高的效率,表面上存储的可能是文本,但在实际处理的时候,是按设置的下标来进行操作,即按INT类型操作,所以效率极高。
ENUM是一个字符串集合,它的成员最多可以有65535个,ENUM字 取值只能是这个集合中的某一个成员(不允许是不同成员的一个组合 ),相当于数学意义上的“排列”。
而SET虽然采用了类似的思路,但允许数据表中的SET字段的取值是集合成员的任意组合(组合数量不得超过64个),相当于数学意义上的“组合”。在内部,这些字符串分别与2的幂(1,2,4,8等)相对应,所以字符串的组合就相当于二进制位的组合 。因为每个安符串分别对应一个二进制位,所以SET类型的空间战胜比ENUM大。
虽然这两种类型的效率相对较高,但由于和其他数据库的不兼容性,因此多创建一个关联数据表来关联这些数据才是更有实用价值。


介绍完MYSQL所支持的所有字段的属性,也该介绍一些在创建数据列的时候涉及到的属性,注意,有一些属性只能用于特定的数据类型

属性名 含义
NULL 数据列可以NULL值(一般是默认设置)
NOT NULL 不允许包含NULL值(因为bTree索引不支持NULL)
DEFAULT xxx 如果输入时没有指定值,则默认以xxx为值
DEFAULT CURRENT_TIMESTAMP 这个在介绍日期时间类型的时候介绍过,默认插入当前时间
ON UPDATE CURRENT_TIMESTAMP 在数据更新的时候,自动更新为当前时间
PRIMARY KEY 定义为主键
AUTO_INCREMENT 自动输入一个序列编号,只能用于整数类型的数据列,一般与主键对应使用,必须与NOT NULL,或UNIQUE 属性同时使用
UNSIGNED 无符号整数,值得注意的是,无论怎么计算,即使是1-2,返回的也是无符号的整数
CHARACTER SET name 仅适用于字符串列,指定一种字符集和一种可选排序方式


虽然MYSQL有DEFAULT XXX这种属性,但实际上,MYSQL并不允许使用函数来设定默认值,比如DEFAULT rand()就不被允许了。

介绍完这些,以后就该介绍数据库的设计技巧了。之所以在介绍设计技巧之前连载了这么长时间的数据类型,是因为在设计中,使用合适的类型可以适当的增加效率,具体的还是看设计吧。

精通MYSQL数据库——连载九

字符串,恐怕应该算是MYSQL里面最复杂的类型了吧?几乎目前所有的问题,都是出在与字符有关的数据列上,大致有几种
1、字符串的查询(以下如果不特指,都是指中文),搜索一个中文的时候,不管是模糊还是精确,往往结果都会有与搜索内容不一致的数据在里面
2、编码,现在大家都知道MYSQL连接上后,先执行一下mysql_query('set names GBK',$conn)这类的语句,从MYSQL4.0升级到4.1及以上版本的朋友在这上面吃的苦不少了。网上关于这类的提问也是最多的
3、索引、效率,varchar是MYSQL所特有的字段,而且长度可变,char则是固定长度的字符串。
在MYSQL所支持的几个字符串格式里面,char和varchar是用的最多的,char是定长字段,,也就是说,不管字符串的实际长度有多少,CHAR(10)将永远占用10个字节。字符串如果前端有空格,那么在存储的时候会自动被数据库去掉,相当于先执行trim($string),再进行存储,如果不满10个字节,将会采用空格填满,读取数据时,MYSQL会自动将这些空格去掉。看到这里,恐怕它的缺点之一就明显的暴露了,CHAR不能存储那些结尾确实有空格的字符串(因为读取时会被MYSQL自动去掉)。


数据类型 含义
char(n) 固定长度的字符串,最多255个字符
varchar(n) 可变长度字符串,最多255个字符(MYSQL<5.0.3,n<=255 , mysql>=5.0.3,n<=65535)
tinytext 可变长度字符串,最多255
text 可变长度字符串,最多65535-1
medinumtext 可变长度字符串,最多16,777,216-1
longtext 可变长度字符串,最多4,294,967,296-1

除了char类型外,其余类型均为可变长度,实际所占空间由该字段所存的内容决定。虽然varchar与tinytext一样都是255个字节,但不同的是varchar可以指定存储的长度,而tinytext只能由存储的时候数据长度而定。
在数据表被创建的时候,MYSQL 把数据列的定义改成一种对MYSQL来说更有效率的形式。这种自动方式的修改称为默许的数据列修改(client column changes)。一般来说是对CHAR和VARCHAR数据列都有影响:如果n<4,varchar(n)将被修改为char(n),而如果n>3并且在同一个数据表里还有其他的可变长度的字段,char将被修改成varchar格式。如果数据表里只有固定长度的数据列,char列将不发生变化。也就是说,你在数据表里的字段如果有多种格式,那么你通过alter table 是无法进行修改的。
上表提到,varchar在新版本里变成了65535个字节,但最大字符个数还是要取决于具体的字符集(GBK中文占两个字节,而UTF8中文则占三个字节)。上面这些所有的数据类型都有一个BINARY属性,一旦该字段添加了这个属性,那么MYSQL就会将他们视同BLOB字段来处理。BINARY的好处是在排序时把字符视为二进制,这样就可以把字母的大小写分开,而且由于是二进制字符串,所耗费的时间也会更短。可惜,在实陆应用中我们存储的大多是中文,所以这一点对我们来说并没有太大的区别。中文,本来就没有大小写之分,再怎么二进制,还是那样。呵呵。
在MYSQL4.0及以前的版本里,各种文本字段的字符集和排序方式都由MYSQL服务器决定,默认值是latin1字符集和瑞典排序方式。虽然允许在MYSQL配置文件里指定一种字符集和排序方式,但这会导致所有的数据库受到影响,还有,对字符集和排序方式做了任何修改都必须重启数据库服务器方能生效,更可恨的是,重启后,还必须重新创建所有的索引,同时,MYSQL4.0之前的版本并不支持UNICODE字符集。
4.1后,这些问题得到了很大的改状况,可以单独为某一个数据列指定一种字符集和排序方式,而且字符集和排序方式的选择范围也大了很多,因为从4.1开始支持了UNICODE和UCS-2等。与字符集及相关排序方式相关的命令是:SHOW COLLATION(必须要注意的是,字符集和排序方式不是随意组合的,每种字符集都有该字符集对应的一些排序方式,而不能混用)。如果没有为某个数据列指定一个字符集和排序方式,它将使用数据表、数据库或MYSQL数据库的默认字符集。至于数据库应该使用哪种字符类型,还是由你的项目所决定,如果你的项目采用了GBK编码,那数据库也同样使用这种编码比较好。如果你在项目初始时对于采用哪种编码未知,那么UTF8应该算是比较好的一种解决方法,数据迁移以及对于JAVA、.net等程序的支持也是最好的,唯一的缺点就是占用数据库空间太大。
说到现在,一直在说latin1和unicode字符集,这代表了什么意思呢?
latin1:在最初的MYSQL版本里都是默认采用了这种字符集,它是符合ISO-8859-1的规范的,收录了西欧国家的常用字符,在那个年代,国内还没有多少人使用MYSQL,而真正使用这些的大多是欧美国家,所以这个字符集主要就是用于收集这些国家常用的字符。随后latin的标准 在不停的变化,有latin2,latin9等,但它们当中并没有一个能够把所有欧洲语言里所有的字符都收录齐全,也就是说latin库里并没有一个可以适用于整个欧洲。
UNICODE:正由于latin不能解决这个问题,所以人们开发出了双字节的UNICODE字符集,两个字集意味着是2的16次方,可以存储65535个字符,所以UNICODE字符集不仅涵盖了所有的欧洲语言,还覆盖了绝大多数的亚洲语言。然而UNICODE只定义了每个字符的编码,没有定义如何存储这些编码。
在这个基础上,也同样发展出了好多变体。最重要的是UCS-2和UTF8,UCS-2又称UTF-16,即每种字符都用两个字节表示,所以几乎所有的字符都被涵盖了。但是这种也是有弊端的:存储空间大了一倍,即使是ASCII字符也是这样;字节编码0会出现在字符串中(比如ASCII写出来的文本里,每一个的第2个字节都是0),可是一些程序会把0当成结束标志,而导致出错。
UTF8是UTF16的替代品,在这里所有的ASCII(7位)仍然象以前一样用第一位是0的单字节表示,所有其他的UNICODE字符用2~4个字节表示。它的缺点也同样明显:同一份文档的字节数和字符数没有任何显而易见的关系,但由于它与现有的程序高度兼容,所以UTF8几乎已经成为了一种事实上的标准,而且大多数软件都把它作为自己的默认字符集。
可惜,PHP发展到现在对于UNICODE的支持还是一般性,并没有内置,处理的时候,不是用ICONV就是mb_string库(PHP6是说内置支持了),但并不能妨碍我们使用UTF8来开发网页。

字符串就介绍到这里。太累了。。。。。这个方面的问题太多了,在以后的连载中遇到再详细说明吧。