Snowfun

导航

 

当数据量达到一定量级的时候,程序的每一个细节,数据库的设计都会影响到系统的性能。这里就数据库开发及优化的话题和大家做个讨论和分析

存储引擎的选择

两种存储引擎是MyISAM和InnoDB

存储引擎区别

1.MyISAM不支持事务,不支持外键,优点是访问速度高,批量插入速度快。假设大量的操作是select、insert,建议采用该存储引擎。但是在我的实际应用中,出现过批量插入过于频繁的时候,当数据量到达一定级别,出现表损坏的情况。

2.InnoDB支持事务处理,但是相对于前者,处理效率低一些,并且其索引及数据也更占用磁盘空间。在存储一些关键数据,并需要对其进行事务操作的时候,我们可以选择innodb,当然,我认为他不应该是访问量太大的。


 

 索引的设计及使用
1. 索引通常是设置where字句中的列,如果你设置select后的列,这是没有任何意义的。当然你需要对某列进行排序,order by后的列也是可以建成索引的。
2. 使用唯一索引,主键就是最好的例子
3. 只要有可能,就要尽量限定索引的长度,例如索引列为 char(100),在其前10个字符大部分都是唯一的,请设置索引的长度为10,使用短索引可以加快查询速度,并节省硬盘空间。
4. 索引的左前缀特性,联合索引实质上也是建立了多个的索引,那么是建立联合索引好还是分别建多个索引好呢?显然前者更好,利用左前缀特性,只要联合索引的最左的列被用到,那么索引都会被使用。

--联合索引的左前缀
--
user是联合索引的名称,包含3个列,分别是username,order,email。
select * from user where username='leehui';
select * from user where pws='123'
--在两句sql中,第一个sql虽然没用上全部的索引列,但由于使用到了最左端的列,所以联合索引还是启用了,第二句没有使用到最左的列,所以索引没有使用。


5. 当然,最后要说的是,不要过度使用索引,索引越多,插入的速度越慢,尤其到数据量庞大时,同时,大量的索引将耗费很多硬盘空间,造成不必要的浪费。

 

使用like的查询,需要注意的是只有列的%不在第一个字符索引才可能被使用

select  itm_cItem,  * from icpItm with( nolock) where itm_cItem like 'PGA%'  --使用到索引itm_cItem
select  itm_cItem,  * from icpItm with( nolock) where itm_cItem like '%PGA%' --沒有使用到索引

 

查看索引使用情况,使用以下命令,代码:

如果索引正在工作,那么Handler_read_key 会很高,如果查询中出现Handler_read_rnd_next的值很高,则表明查询低效,索引的应用并不合理。

mysql> show status like 'Handler_read_key';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| Handler_read_key | 0     |
+------------------+-------+
1 row in set (0.00 sec)

 

 

 提升数据库性能

 

1.选取最适用的字段属性
数据库中的表越小,执行的查询也就会越快。为了获得更好的性能,在创建表的时候可以将表中字段的宽度设得尽可

能小.
尽量使用MEDIUMINT而不是BIGIN来定义整型字段。

Integer Text
tinyint(-128到127) char--255
smallint(-32768到32767) varchar--65535
mediumint(-8388608到8388607) tinyText--255
int(正负21亿) Text--65535
bigint() mediumText--16777215
  LongText

 另外一个提高效率的方法是在可能的情况下,应该尽量把字段设置为NOT NULL,这样在将来执行查询的时候,数据库不用去比较NULL值。对于某些文本字段,例如“省份”或者“性别”,我们可以将它们定义为ENUM类型。因为在MySQL中,ENUM类型被当作数值型数据来处理,而数值型数据被处理起来的速度要比文本类型快得多。这样,我们又可以提高数据库的性能。

 

2.使用连接(JOIN)来代替子查询(Sub-Queries)
例如,我们要将客户基本信息表中没有任何订单的客户删除掉
DELETE FROM customerinfo WHERE CustomerID NOT in (SELECT CustomerID FROM salesinfo )
如果使用连接(JOIN).. 来完成这个查询工作,速度将会快很多。尤其是当salesinfo表中对CustomerID建有索引的话

,性能将会更好,查询如下:
SELECT * FROM customerinfo
LEFT JOIN salesinfoON customerinfo.CustomerID=salesinfo. CustomerID WHERE salesinfo.CustomerID IS NULL
连接(JOIN).. 之所以更有效率一些,是因为 MySQL不需要在内存中创建临时表来完成这个逻辑上的需要两个步骤的

查询工作。


3.事务
使用事务,它的作用是:要么语句块中每条语句都操作成功,要么都失败。换句话说,就是可以保持数据库中数据的

一致性和完整性。事物以BEGIN 关键字开始,COMMIT关键字结束。在这之间的一条SQL操作失败,那么,ROLLBACK命

令就可以把数据库恢复到BEGIN开始之前的状态。
事务的另一个重要作用是当多个用户同时使用相同的数据源时,它可以利用锁定数据库的方法来为用户提供一种安全

的访问方式,这样可以保证用户的操作不被其它的用户所干扰。

4.锁定表
由于在事务执行的过程中,数据库将会被锁定,因此其它的用户请求只能暂时等待直到该事务结束。就会产生比较严

重的响应延迟。
有些情况下我们可以通过锁定表的方法来获得更好的性能。下面的例子就用锁定表的方法来完成前面一个例子中事务

的功能。
LOCK TABLE inventory WRITE
SELECT Quantity FROM inventory WHERE Item='book';
...
UPDATE inventory SET Quantity=11 WHEREItem='book';
UNLOCK TABLES
包含有 WRITE 关键字的LOCK TABLE 语句可以保证在 UNLOCK TABLES 命令被执行之前,不会有其它的访问来对

inventory 进行插入、更新或者删除的操作。

 

 

5.使用外键
CREATE TABLE customerinfo
(
 CustomerID INT NOT NULL ,
 PRIMARY KEY ( CustomerID )
) TYPE = INNODB;

CREATE TABLE salesinfo
(
 SalesID INT NOT NULL,
 CustomerID INT NOT NULL,
 PRIMARY KEY(CustomerID, SalesID),
 FOREIGN KEY (CustomerID) REFERENCES customerinfo (CustomerID) ON DELETE CASCADE
) TYPE = INNODB;
注意例子中的参数“ON DELETE CASCADE”。该参数保证当 customerinfo 表中的一条客户记录被删除的时候,salesinfo 表中所有与该客户相关的记录也会被自动删除。如果要在 MySQL 中使用外键,一定要记住在创建表的时候将表的类型定义为事务安全表 InnoDB类型。该类型不是 MySQL 表的默认类型。定义的方法是在 CREATE TABLE 语句中加上 TYPE=INNODB。


6.使用索引
索引是提高数据库性能的常用方法,它可以令数据库服务器以比没有索引快得多的速度检索特定的行,尤其是在查询语句当中包含有MAX(), MIN()和ORDERBY这些命令的时候,性能提高更为明显。那该对哪些字段建立索引呢?一般说来,索引应建立在那些将用于JOIN, WHERE判断和ORDER BY排序的字段上。尽量不要对数据库中某个含有大量重复的值的字段建立索引。对于一个ENUM类型的字段来说,出现大量重复值是很有可能的情况,例如customerinfo中的“province”.. 字段,在这样的字段上建立索引将不会有什么帮助;相反,还有可能降低数据库的性能。

我们在创建表的时候可以同时创建合适的索引,也可以使用ALTER TABLE或CREATE INDEX在以后创建索引。此外,MySQL从版本3.23.23开始支持全文索引和搜索。全文索引在MySQL 中是一个FULLTEXT类型索引,但仅能用于MyISAM 类型的表。对于一个大的数据库,将数据装载到一个没有FULLTEXT索引的表中,然后再使用ALTER TABLE或CREATE INDEX创建索引,将是非常快的。但如果将数据装载到一个已经有FULLTEXT索引的表中,执行过程将会非常慢。

 

 

7.优化的查询语句
使用索引可以提高查询的速度,但如果SQL语句使用不恰当的话,索引将无法发挥它应有的作用。
注意:
7.1最好是在相同类型的字段间进行比较的操作。
例如不能将一个建有索引的INT字段和BIGINT字段进行比较;但是作为特殊的情况,在CHAR类型的字段和VARCHAR类型字段的字段大小相同的时候,可以将它们进行比较
7.2在建有索引的字段上尽量不要使用函数进行操作。
例如:在一个DATE类型的字段上使用YEAE()函数时,将会使索引不能发挥应有的作用。查询虽然返回的结果一样,但后者要比前者快得多。
SELECT * FROM order WHERE YEAR(OrderDate)<2001;
SELECT * FROM order WHERE OrderDate<"2001-01-01";
SELECT * FROM inventory WHERE Amount/7<24;
SELECT * FROM inventory WHERE Amount<24*7;
7.3搜索字符型字段时,我们有时会使用 LIKE 关键字和通配符,这种做法虽然简单,但却也是以牺牲系统性能为代价的
例如:查询将会比较表中的每一条记录。SELECT * FROM books WHERE name like "MySQL%" 但是如果换用下面的查询,返回的结果一样,但速度就要快上很多:SELECT * FROM books WHERE name>="MySQL"and name<"MySQM"

 

 

 

 

 

 

 


 

 

 

posted on 2011-08-24 15:49  Snowfun  阅读(405)  评论(0)    收藏  举报