设计数据库之经验谈

 更新时间:2016年11月25日 16:43  点击:1586
数据库设计经验谈
数据库模型的设计是否合理会极大影响系统的使用性能。笔者依据多年来设计和使用数据库的经验,提出以下一些设计原则,供同仁们参考。
慎用游标(Cursor)
游标提供了对特定集合中逐行扫描的手段,一般使用游标来逐行遍历数据,根据取出数据条件的不同进行不同的操作。而对于多表和大表中定义的游标(大的数据集合)循环很容易使程序进入一个漫长的等待甚至死机,笔者在某市“住房公积金管理系统”进行日终账户滚积数计息处理时,对一个10万个账户的游标处理时导致程序进入了一个无限期的等待(后经测算需48小时才能完成)(硬件环境:Alpha/4000 128MB RAM ,SCO Unix ,Sybase 11.0)。经修改程序并改用UPDATE语句后,该处理过程得以在20分钟之内完成。示例如下:
Declare Mycursor cursor for select count—no from COUNT  
Open Mycursor
Fetch Mycursor into @vcount—no
While (@@sqlstatus=0)
Begin
If @vcount—no=′ ′ 条件1
操作1
If @vcount—no=′ ′ 条件2
操作2
...
Fetch Mycursor into @vcount—no
End
 ...
改为
Update COUNT set 操作1 for 条件1
Update COUNT set 操作2 for 条件2
...
在某些必须使用游标的场合,可考虑将符合条件的数据行转入临时表中,再对临时表定义游标进行操作,这样,可使性能得到明显提高。笔者在某地市“电信收费系统”数据库后台程序设计中,对一个表(3万行中符合条件的30多行数据)进行游标操作(硬件环境:PC服务器,PⅡ266 64MB RAM ,Windows NT4.0 MS SQL Server 6.5)。
示例如下:
Create #tmp /* 定义临时表 */
 ( 字段1
  字段2
   ... )
Insert into #tmp select * from TOTAL where 条件
Declare Mycursor cursor for select * from #tmp /*对临时表定义游标*/
 ...
索引(Index)的使用技巧
创建索引一般有两个目的:维护被索引列的惟一性和提供快速访问表中数据的策略。大型数据库有两种索引,即簇索引和非簇索引,一个没有簇索引的表是按堆结构存储数据,所有的数据均添加在表的尾部;而建立了簇索引的表,其数据在物理上会按照簇索引键的顺序存储,一个表只允许有一个簇索引,因此,根据B树结构,可以理解添加任何一种索引均能提高按索引列查询的速度,但与此同时会降低插入、更新、删除操作的性能,尤其是当填充因子(Fill Factor)较大时。所以对索引较多的表进行频繁的插入、更新、删除操作时,建表和索引时应设置较小的填充因子,以便在各数据页中留下较多的自由空间,减少页分割及重新组织的工作。
要创建一个可以每个小时报告的查询,首先要创建一个表格。该表格一列记录日期,而没有时间信息;另一列记录钟点。下面的表格有一列记录了不同的处理类型。例如,我们可以按小时找出处理类型的总数。
CREATE TABLE test
(StartTime DATETIME NOT NULL
DEFAULT CURRENT_TIMESTAMP,
StartDate DATETIME NOT NULL
DEFAULT CONVERT(DATETIME, CONVERT(CHAR(10),CURRENT_TIMESTAMP, 110)),
StartHour INT NOT NULL
DEFAULT DATEPART(hh,CURRENT_TIMESTAMP),
TranType INT NOT NULL
CONSTRAINT ck_TranType CHECK ( TranType IN
(
1, -- insert
2, -- update
3, -- delete
)
DEFAULT 1
)
GO
接下来,插入test的数据来模拟一个可能的样本。
INSERT test (StartTime, TranType) VALUES (CURRENT_TIMESTAMP, 3)
INSERT test (StartTime, TranType) VALUES (CURRENT_TIMESTAMP, 2)
INSERT test (StartTime, TranType) VALUES (CURRENT_TIMESTAMP, 3)
GO
DECLARE @hr int
SET @hr = DATEPART(hh, DATEADD(hh,-1,CURRENT_TIMESTAMP) )
INSERT test (StartTime, TranType, StartHour) _
VALUES (DATEADD(hh,-1,CURRENT_TIMESTAMP), 3, @hr)
INSERT test (StartTime, TranType, StartHour) _
VALUES (DATEADD(hh,-1,CURRENT_TIMESTAMP), 1, @hr)
INSERT test (StartTime, TranType, StartHour) _
VALUES (DATEADD(hh,-1,CURRENT_TIMESTAMP), 2, @hr)
GO
然后用一个查询来找出按日和小时的处理总数。
SELECT StartDate tran_day,
StartHour tran_hour
, CASE trantype WHEN 1 THEN 'insert'
WHEN 2 THEN 'update'
WHEN 3 THEN 'delete'
ELSE 'unknown'
END trantype,
COUNT(*) tran_total
FROM
Test
GROUP BY
StartDate,
StartHour
,trantype
ORDER BY StartDate, StartHour
COMPUTE SUM(COUNT(*)) BY StartDate, StartHour
GO

去掉test可以清空test表格。
DROP TABLE test
GO

MYSQL到ORACLE程序迁移的注意事项
2001-09
有很多应用项目, 刚起步的时候用MYSQL数据库基本上能实现各种功能需求,随着应用用户的增多,
数据量的增加,MYSQL渐渐地出现不堪重负的情况:连接很慢甚至宕机,于是就有把数据从MYSQL迁到
ORACLE的需求,应用程序也要相应做一些修改。本人总结出以下几点注意事项,希望对大家有所帮助。
1. 自动增长的数据类型处理
MYSQL有自动增长的数据类型,插入记录时不用操作此字段,会自动获得数据值。
ORACLE没有自动增长的数据类型,需要建立一个自动增长的序列号,插入记录时要把序列号的下一个
值赋于此字段。
CREATE SEQUENCE 序列号的名称 (最好是表名 序列号标记) INCREMENT BY 1 START WITH 1
MAXVALUE 99999 CYCLE NOCACHE;
其中最大的值按字段的长度来定, 如果定义的自动增长的序列号 NUMBER(6) , 最大值为999999
INSERT 语句插入这个字段值为: 序列号的名称.NEXTVAL
2. 单引号的处理
MYSQL里可以用双引号包起字符串,ORACLE里只可以用单引号包起字符串。在插入和修改字符串
前必须做单引号的替换:把所有出现的一个单引号替换成两个单引号。
3. 翻页的SQL语句的处理
MYSQL处理翻页的SQL语句比较简单,用LIMIT 开始位置, 记录个数;PHP里还可以用SEEK定位到结果
集的位置。
ORACLE处理翻页的SQL语句就比较繁琐了。每个结果集只有一个ROWNUM字段标明它的位置, 并且只能
用ROWNUM<100, 不能用ROWNUM>80。
以下是经过分析后较好的两种ORACLE翻页SQL语句( ID是唯一关键字的字段名 ):
语句一:
SELECT ID, [FIELD_NAME,...] FROM TABLE_NAME WHERE ID IN ( SELECT ID FROM (SELECT
ROWNUM AS NUMROW, ID FROM TABLE_NAME WHERE 条件1 ORDER BY 条件2) WHERE NUMROW > 80 AND
NUMROW < 100 ) ORDER BY 条件3;

语句二:
SELECT * FROM (( SELECT ROWNUM AS NUMROW, c.* from (select [FIELD_NAME,...] FROM
TABLE_NAME WHERE 条件1 ORDER BY 条件2) c) WHERE NUMROW > 80 AND NUMROW < 100 ) ORDER BY 条件3;
4. 长字符串的处理
长字符串的处理ORACLE也有它特殊的地方。INSERT和UPDATE时最大可操作的字符串长度小于等于
在Linux界享有很高声誉的MySQL数据库,以其小巧玲珑、功能强大、全免费而著称。但对于很多用户来说,有时候必须要在Windows浏览、分析其中的数据,而在Windows下,MySQL数据库文件是无法被其他程序读取的。所以有人编写了这个格式转换程序---MySQL-to-Access。它可以把MySQL格式数据库文件转换为普通Access数据库文件,方便我们在Windows下轻松编辑、浏览其中的数据了。它适用于所有操作系统版本的MySQL数据库转换。
  大家可以到http://crctimes.onlinedown.net/down/sql2accd.exe下载这一程序。

MySQL以速度为目标
--------------------------------------------------------------------------------
MySQL和PostgreSQL都是非常著名的数据库开放源码项目,而且都有取代商用数据库系统的趋势,但两者有着不同的设计目标。一般而言,如果需要更快的速度,可以优先考虑MySQL,而如果需要一些新的特色,那可以选择PostgreSQL。
目前MySQL由MySQL AB公司维护,其最新稳定版本为3.23,支持事务处理的3.23Max版也进入了Beta测试阶段,而它的最新开发版本4.0已经进入了Alpha测试阶段。它略显不寻常的许可费用,很容易让用户对它印象深刻。它的价格随平台和安装方式的不同而改变,其Windows版本在任何情况下都不免费,而对任何Unix/Linux版本,如果用户或系统管理员自己安装是免费的,第三方安装则必须支付许可费用。
MySQL是基于C/S体系结构的网络数据库管理系统。它的设计以速度为主要目标,可以快速处理多个用户的查询请求,在处理客户端连接时的速度也非常快,很适合用做Web站点的后台数据库。相对而言,PostgreSQL的执行速度比较慢,它对每个连接都生成一个子进程,而生成子进程、建立后台服务进程的步骤减慢了它的执行速度。MySQL的服务器功能很紧凑,各种复杂的功能处理(比如XML支持)完全被放到客户端进行,这使得增加功能时不会牺牲数据库服务器的速度和可靠性。而且它已被商业内存检测程序证明不存在内存泄露,连续中断和程序崩溃的现象也很罕见,在稳定性上比PostgreSQL要强一些。
在最初的设计阶段,MySQL主要面向中等规模的数据库,也就是说,数据库的规模大约有几千万行,每个表大约100MB。随着MySQL项目的发展,它的使用领域也逐渐扩展到TB规模的大型数据库和小型的手持或嵌入式设备领域。但是在短期内,MySQL不会支持实时数据库或大规模集群数据库。虽然在其3.23版本中,它通过MyISAM表,可以使系统在理论上能够支持8000PB的表。但由于操作系统的限制,在大部分Linux系统下,它仅能处理最大为2GB或4GB的表。在3.23版本中,还加入了支持大型服务器集群的复制、InnoDB的事务表处理器、Berkerley DB事务表处理器接口、全文本搜索、MyODBC 2.5接口、MyISAM表的自动检查和修复、批量插入等新模块。
InnoDB和BDB事务表处理器的引入使MySQL中使用这些方式存储的数据表具有很好的事务处理能力。不过对于其他方式存储的表,使用原子操作维护完整性和一致性通常会损失一些性能。在完整性非常重要时,可以使用LOCK TABLES进行表锁定。从3.23.44开始,InnoDB表支持外码限制检查,不过它的使用,特别是误用外码可能会导致较严重的问题。
[!--infotagslink--]

相关文章

  • PHP 数据库缓存Memcache操作类

    操作类就是把一些常用的一系列的数据库或相关操作写在一个类中,这样调用时我们只要调用类文件,如果要执行相关操作就直接调用类文件中的方法函数就可以实现了,下面整理了...2016-11-25
  • C#连接SQL数据库和查询数据功能的操作技巧

    本文给大家分享C#连接SQL数据库和查询数据功能的操作技巧,本文通过图文并茂的形式给大家介绍的非常详细,需要的朋友参考下吧...2021-05-17
  • photoshop设计一幅大鱼海棠动画片海报制作实例教程

    今天小编在这里就来给各位photoshop的这一款软件的使用者们来说一说设计一幅大鱼海棠动画片海报制作的实例教程,各位想知道具体制作步骤的使用者们,那么各位就快来看看...2016-09-14
  • php简单数据操作的实例

    最基础的对数据的增加删除修改操作实例,菜鸟们收了吧...2013-09-26
  • C#从数据库读取图片并保存的两种方法

    这篇文章主要介绍了C#从数据库读取图片并保存的方法,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下...2021-01-16
  • 解决Mybatis 大数据量的批量insert问题

    这篇文章主要介绍了解决Mybatis 大数据量的批量insert问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-01-09
  • Antd-vue Table组件添加Click事件,实现点击某行数据教程

    这篇文章主要介绍了Antd-vue Table组件添加Click事件,实现点击某行数据教程,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-11-17
  • 详解如何清理redis集群的所有数据

    这篇文章主要介绍了详解如何清理redis集群的所有数据,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-02-18
  • Intellij IDEA连接Navicat数据库的方法

    这篇文章主要介绍了Intellij IDEA连接Navicat数据库的方法,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借价值,需要的朋友可以参考下...2021-03-25
  • 在数据库里将毫秒转换成date格式的方法

    在开发过程中,我们经常会将日期时间的毫秒数存放到数据库,但是它对应的时间看起来就十分不方便,我们可以使用一些函数将毫秒转换成date格式。 一、 在MySQL中,有内置的函数from_unixtime()来做相应的转换,使用如下: 复制...2014-05-31
  • vue 获取到数据但却渲染不到页面上的解决方法

    这篇文章主要介绍了vue 获取到数据但却渲染不到页面上的解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-11-19
  • C#操作本地文件及保存文件到数据库的基本方法总结

    C#使用System.IO中的文件操作方法在Windows系统中处理本地文件相当顺手,这里我们还总结了在Oracle中保存文件的方法,嗯,接下来就来看看整理的C#操作本地文件及保存文件到数据库的基本方法总结...2020-06-25
  • 如何解决局域网内mysql数据库连接慢

    通过内网连另外一台机器的mysql服务, 确发现速度N慢! 等了大约几十秒才等到提示输入密码。 但是ping mysql所在服务器却很快! 想到很久之前有过类似的经验, telnet等一些服务在连接请求的时候,会做一些反向域名解析(如果...2015-10-21
  • php把读取xml 文档并转换成json数据代码

    在php中解析xml文档用专门的函数domdocument来处理,把json在php中也有相关的处理函数,我们要把数据xml 数据存到一个数据再用json_encode直接换成json数据就OK了。...2016-11-25
  • MySQL快速复制数据库数据表的方法

    某些时候,例如为了搭建一个测试环境,或者克隆一个网站,需要复制一个已存在的mysql数据库。使用以下方法,可以非常简单地实现。假设已经存在的数据库名字叫db1,想要复制一份,命名为newdb。步骤如下:1. 首先创建新的数据库newd...2015-10-21
  • ps怎么制作倒影 ps设计倒影的方法

    ps软件是一款非常不错的图片处理软件,有着非常不错的使用效果。这次文章要给大家介绍的是ps怎么制作倒影,一起来看看设计倒影的方法。 用ps怎么做倒影最终效果&#819...2017-07-06
  • mybatis-plus 处理大数据插入太慢的解决

    这篇文章主要介绍了mybatis-plus 处理大数据插入太慢的解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-12-18
  • mysqldump命令导入导出数据库方法与实例汇总

    mysqldump命令的用法1、导出所有库系统命令行mysqldump -uusername -ppassword --all-databases > all.sql 2、导入所有库mysql命令行mysql>source all.sql; 3、导出某些库系统命令行mysqldump -uusername -ppassword...2015-10-21
  • Mysql数据库错误代码中文详细说明

    1005:创建表失败1006:创建数据库失败1007:数据库已存在,创建数据库失败1008:数据库不存在,删除数据库失败1009:不能删除数据库文件导致删除数据库失败1010:不能删除数据目录导致删除数据库失败1011:删除数据库...2013-09-23
  • C语言程序设计第五版谭浩强课后答案(第二章答案)

    这篇文章主要介绍了C语言程序设计第五版谭浩强课后答案(第二章答案),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2021-04-02