精华内容
下载资源
问答
  • 常见数据库有哪几种?

    千次阅读 2020-06-01 10:58:29
    SQL(StructuredQueryLanguage,结构化查询语言)是一种数据库查询语言和程序设计语言,主要用于管理数据库中的数据,如存取数据、查询数据、更新数据等。 SQL是IBM公司于1975—1979年之间开发出来的,在20世纪随着...

    数据库有两种类型,分别是关系型数据库与非关系型数据库。
    1、关系数据库
    包括:MySQL、MariaDB(MySQL的代替品,英文维基百科从MySQL转向MariaDB)、Percona Server(MySQL的代替品)、PostgreSQL、Microsoft Access、Microsoft SQL Server、Google Fusion Tables。
    FileMaker、Oracle数据库、Sybase、dBASE、Clipper、FoxPro、foshub。几乎所有的数据库管理系统都配备了一个开放式数据库连接(ODBC)驱动程序,令各个数据库之间得以互相集成。

    2、非关系型数据库(NoSQL)
    包括:BigTable(Google)、Cassandra、MongoDB、CouchDB、键值(key-value)数据库、Apache Cassandra(为Facebook所使用):高度可扩展、Dynamo、LevelDB(Google)。

    SQL(StructuredQueryLanguage,结构化查询语言)是一种数据库查询语言和程序设计语言,主要用于管理数据库中的数据,如存取数据、查询数据、更新数据等。

    SQL是IBM公司于1975—1979年之间开发出来的,在20世纪随着数据库技术的发展,数据库产品越来越多,如Oracle、DB2、MongoDB、SQLServer、MySQL等。

    1. Oracle数据库
    Oracle数据库管理系统是由甲骨文(Oracle)公司开发的,在数据库领域一直处于领先地位。目前,Oracle数据库覆盖了大、中、小型计算机等几十种计算机型,成为世界上使用最广泛的关系型数据管理系统(由二维表及其之间的关系组成的一个数据库)之一。

    Oracle数据库管理系统采用标准的SQL,并经过美国国家标准技术所(NIST)测试。与IBMSQL/DS、DB2、INGRES、IDMS/R等兼容,而且它可以在VMS、DOS、UNIX、Windows等操作系统下工作。不仅如此,Oracle数据库管理系统还具有良好的兼容性、可移植性和可连接性。

    2. SQLServer数据库
    SQLServer是由微软公司开发的一种关系型据库管理系统,它已广泛用于电子商务、银行、保险、电力等行业。SQLServer提供了对XML和Internet标准的支持,具有强大的、灵活的、基于Web的应用程序管理功能。而且界面友好、易于操作,深受广大用户的喜爱,但它只能在Windows平台上运行,并对操作系统的稳定性要求较高,因此很难处理日益增长的用户数量。

    3. DB2数据库
    DB2数据库是由IBM公司研制的一种关系型数据库管理系统,主要应用于OS/2、Windows等平台下,具有较好的可伸缩性,可支持从大型计算机到单用户环境。

    DB2支持标准的SQL,并且提供了高层次的数据利用性、完整性、安全性和可恢复性,以及从小规模到大规模应用程序的执行能力,适合于海量数据的存储,但相对于其他数据库管理系统而言,DB2的操作比较复杂。

    4. MongoDB数据库

    MongoDB是由10gen公司开发的一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似JSON的bjson格式,因此可以存储比较复杂的数据类型。

    Mongo数据库管理系统最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。不仅如此,它还是一个开源数据库,并且具有高性能、易部署、易使用、存储数据非常方便等特点。对于大数据量、高并发、弱事务的互联网应用,MongoDB完全可以满足Web2.0和移动互联网的数据存储需求。

    5. MySQL数据库

    MySQL数据库管理系统是由瑞典的MySQLAB公司开发的,但是几经辗转,现在是Oracle产品。它是以“客户/服务器”模式实现的,是一个多用户、多线程的小型数据库服务器。而且MySQL是开源数据的,任何人都可以获得该数据库的源代码并修正MySQL的缺陷。MySQL具有跨平台的特性,它不仅可以在Windows平台上使用,还可以在UNIX、Linux和MacOS等平台上使用。相对其他数据库而言,MySQL的使用更加方便、快捷,而且MySQL是免费的,运营成本低,因此,越来越多的公司开始使用MySQL。
    6. Sybase数据库
    美国Sybase公司研制的一种关系型数据库系统,是一种典型的UNIX或WindowsNT平台上客户机/服务器环境下的大型数据库系统。
    特点:
    1、客户/服务器体系结构
    2、真正开放的
    3、高性能的

    展开全文
  • 文章目录数据库介绍数据库管理系统-简称(DBMS)数据库管理系统-主要功能数据库的类型1. 关系数据库2. 非关系型数据库(NoSQL)数据库模型数据库的架构数据库索引数据库操作:事务 数据库介绍 数据库,简而言之可视...

    数据库介绍

    数据库,简而言之可视为电子化的文件柜——存储电子文件的处所,用户可以对文件中的数据进行新增、查询、更新、删除等操作。
    所谓“数据库”是以一定方式储存在一起、能予多个用户共享、具有尽可能小的冗余度、与应用程序彼此独立的数据集合。

    数据库管理系统-简称(DBMS)

    数据库管理系统(Database Management System)是一种操纵和管理数据库的大型软件,用于建立、使用和维护数据库,简称DBMS。它对数据库进行统一的管理和控制,以保证数据库的安全性和完整性。用户通过DBMS访问数据库中的数据,数据库管理员也通过dbms进行数据库的维护工作。它可使多个应用程序和用户用不同的方法在同时或不同时刻去建立,修改和询问数据库。大部分DBMS提供数据定义语言DDL(Data Definition Language)和数据操作语言DML(Data Manipulation Language),供用户定义数据库的模式结构与权限约束,实现对数据的追加、删除等操作。
    数据库管理系统是数据库系统的核心,是管理数据库的软件。数据库管理系统就是实现把用户意义下抽象的逻辑数据处理,转换成为计算机中具体的物理数据处理的软件。有了数据库管理系统,用户就可以在抽象意义下处理数据,而不必顾及这些数据在计算机中的布局和物理位置。

    数据库管理系统-主要功能

    1.数据定义:DBMS提供数据定义语言DDL(Data Definition Language),供用户定义数据库的三级模式结构、两级映像以及完整性约束和保密限制等约束。DDL主要用于建立、修改数据库的库结构。DDL所描述的库结构仅仅给出了数据库的框架,数据库的框架信息被存放在数据字典(Data Dictionary)中。
    2.数据操作:DBMS提供数据操作语言DML(Data Manipulation Language),供用户实现对数据的追加、删除、更新、查询等操作。
    3.数据库的运行管理:数据库的运行管理功能是DBMS的运行控制、管理功能,包括多用户环境下的并发控制、安全性检查和存取限制控制、完整性检查和执行、运行日志的组织管理、事务的管理和自动恢复,即保证事务的原子性。这些功能保证了数据库系统的正常运行。
    4.数据组织、存储与管理:DBMS要分类组织、存储和管理各种数据,包括数据字典、用户数据、存取路径等,需确定以何种文件结构和存取方式在存储级上组织这些数据,如何实现数据之间的联系。数据组织和存储的基本目标是提高存储空间利用率,选择合适的存取方法提高存取效率。
    5.数据库的保护:数据库中的数据是信息社会的战略资源,所以数据的保护至关重要。DBMS对数据库的保护通过4个方面来实现:数据库的恢复、数据库的并发控制、数据库的完整性控制、数据库安全性控制。DBMS的其他保护功能还有系统缓冲区的管理以及数据存储的某些自适应调节机制等。
    6.数据库的维护:这一部分包括数据库的数据载入、转换、转储、数据库的重组合重构以及性能监控等功能,这些功能分别由各个使用程序来完成。
    7.通信:DBMS具有与操作系统的联机处理、分时系统及远程作业输入的相关接口,负责处理数据的传送。对网络环境下的数据库系统,还应该包括DBMS与网络中其他软件系统的通信功能以及数据库之间的互操作功能。

    数据库的类型

    1. 关系数据库

    ⚫ MySQL
    ⚫ MariaDB(MySQL的代替品,英文维基百科从MySQL转向MariaDB)
    ⚫ Percona Server(MySQL的代替品·)
    ⚫ PostgreSQL
    ⚫ Microsoft Access
    ⚫ Microsoft SQL Server
    ⚫ Google Fusion Tables
    ⚫ FileMaker
    ⚫ Oracle数据库
    ⚫ Sybase
    ⚫ dBASE
    ⚫ Clipper
    ⚫ FoxPro
    ⚫ foshub

    2. 非关系型数据库(NoSQL)

    ⚫ NoSQL
    ⚫ BigTable(Google)
    ⚫ Cassandra
    ⚫ MongoDB
    ⚫ CouchDB
    ⚫ 键值(key-value)数据库
    ⚫ Apache Cassandra(为Facebook所使用):高度可扩展
    ⚫ Dynamo
    ⚫ LevelDB(Google)

    数据库模型

    ⚫ 对象模型
    ⚫ 层次模型(轻量级数据访问协议)
    ⚫ 网状模型(大型数据储存)
    ⚫ 关系模型
    ⚫ 面向对象模型
    ⚫ 半结构化模型
    ⚫ 平面模型(表格模型,一般在形式上是一个二维数组。如表格模型数据Excel)

    数据库的架构

    ⚫ 数据库的架构可以大致区分为三个概括层次:内层、概念层和外层。
    ⚫ 内层:最接近实际存储体,亦即有关数据的实际存储方式。
    ⚫ 外层:最接近用户,即有关个别用户观看数据的方式。
    ⚫ 概念层:介于两者之间的间接层。

    数据库索引

    数据索引的观念由来已久,像是一本书前面几页都有目录,目录也算是索引的一种,只是它的分类较广,例如车牌、身份证字号、条码等,都是一个索引的号码,当我们看到号码时,可以从号码中看出其中的端倪,若是要找的人、车或物品,也只要提供相关的号码,即可迅速查到正确的人事物。
    另外,索引跟字段有着相应的关系,索引即是由字段而来,其中字段有所谓的关键字段(Key Field),该字段具有唯一性,即其值不可重复,且不可为"空值(null)"。例如:在合并数据时,索引便是扮演欲附加字段数据之指向性用途的角色。故此索引为不可重复性且不可为空。

    数据库操作:事务

    事务(transaction)是用户定义的一个数据库操作序列,这些操作要么全做,要么全不做,是一个不可分割的工作单位。 事务的ACID(数据库事务正确执行的四个基本要素的缩写)特性:
    ⚫ 基元性(atomicity)
    ⚫ 一致性(consistency)
    ⚫ 隔离性(isolation)
    ⚫ 持续性(durability)
    ⚫ 事务的并发性是指多个事务的并行操作轮流交叉运行,事务的并发可能会访问和存储不正确的数据,破坏交易的隔离性和数据库的一致性。
    ⚫ 网状数据模型的数据结构 网状模型 满足下面两个条件的基本层次联系的集合为网状模型。

    1. 允许一个以上的结点无双亲;
    2. 一个结点可以有多于一个的双亲。

    转载参考地址:https://baike.baidu.com/item/数据库/103728?fr=aladdin

    数据库基本----SQL语句大全

    一、基础
    
        1、说明:创建数据库
        Create DATABASE database-name
    
        2、说明:删除数据库
        drop database dbname
    
        3、说明:备份sql server
        --- 创建 备份数据的 device
        USE master
        EXEC sp_addumpdevice 'disk', 'testBack', 'c:/mssql7backup/MyNwind_1.dat'
        --- 开始 备份
        BACKUP DATABASE pubs TO testBack
    
        4、说明:创建新表
        create table tabname(col1 type1 [not null] [primary key],col2 type2 [not null],..)
        根据已有的表创建新表:
        A:create table tab_new like tab_old (使用旧表创建新表)
        B:create table tab_new as select col1,col2… from tab_old definition only
    
        5、说明:删除新表
        drop table tabname
    
        6、说明:增加一个列
        Alter table tabname add column col type
        注:列增加后将不能删除。DB2中列加上后数据类型也不能改变,唯一能改变的是增加varchar类型的长度。
    
        7、说明:添加主键: Alter table tabname add primary key(col)
        说明:删除主键: Alter table tabname drop primary key(col)
    
        8、说明:创建索引:create [unique] index idxname on tabname(col….)
        删除索引:drop index idxname
        注:索引是不可更改的,想更改必须删除重新建。
    
        9、说明:创建视图:create view viewname as select statement
        删除视图:drop view viewname
    
        10、说明:几个简单的基本的sql语句
        选择:select * from table1 where 范围
        插入:insert into table1(field1,field2) values(value1,value2)
        删除:delete from table1 where 范围
        更新:update table1 set field1=value1 where 范围
        查找:select * from table1 where field1 like ’%value1%---like的语法很精妙,查资料!
        排序:select * from table1 order by field1,field2 [desc]
        总数:select count as totalcount from table1
        求和:select sum(field1) as sumvalue from table1
        平均:select avg(field1) as avgvalue from table1
        最大:select max(field1) as maxvalue from table1
        最小:select min(field1) as minvalue from table1
    
        11、说明:几个高级查询运算词
        AUNION 运算符
        UNION 运算符通过组合其他两个结果表(例如 TABLE1TABLE2)并消去表中任何重复行而派生出一个结果表。当 ALLUNION 一起使用时(即 UNION ALL),不消除
    
    重复行。两种情况下,派生表的每一行不是来自 TABLE1 就是来自 TABLE2BEXCEPT 运算符
        EXCEPT 运算符通过包括所有在 TABLE1 中但不在 TABLE2 中的行并消除所有重复行而派生出一个结果表。当 ALLEXCEPT 一起使用时 (EXCEPT ALL),不消除重复行。
        CINTERSECT 运算符
        INTERSECT 运算符通过只包括 TABLE1TABLE2 中都有的行并消除所有重复行而派生出一个结果表。当 ALLINTERSECT 一起使用时 (INTERSECT ALL),不消除重复
    
    行。注:使用运算词的几个查询结果行必须是一致的。
    
        12、说明:使用外连接
        A、left outer join:
        左外连接(左连接):结果集几包括连接表的匹配行,也包括左连接表的所有行。
        SQL: select a.a, a.b, a.c, b.c, b.d, b.f from a LEFT OUT JOIN b ON a.a = b.c
        B:right outer join:
        右外连接(右连接):结果集既包括连接表的匹配连接行,也包括右连接表的所有行。
        C:full outer join:
        全外连接:不仅包括符号连接表的匹配行,还包括两个连接表中的所有记录。
    
    二、提升
    
        1、说明:复制表(只复制结构,源表名:a 新表名:b) (Access可用)
        法一:select * into b from a where 1<>1
        法二:select top 0 * into b from a
    
        2、说明:拷贝表(拷贝数据,源表名:a 目标表名:b) (Access可用)
        insert into b(a, b, c) select d,e,f from b;
    
        3、说明:跨数据库之间表的拷贝(具体数据使用绝对路径) (Access可用)
        insert into b(a, b, c) select d,e,f from b in ‘具体数据库’ where 条件
        例子:..from b in '"&Server.MapPath("."&"/data.mdb" &"' where..
    
        4、说明:子查询(表名1:a 表名2:b)
        select a,b,c from a where a IN (select d from b   或者: select a,b,c from a where a IN (1,2,3)
    
        5、说明:显示文章、提交人和最后回复时间
        select a.title,a.username,b.adddate from table a,(select max(adddate) adddate from table where table.title=a.title) b
    
        6、说明:外连接查询(表名1:a 表名2:b)
        select a.a, a.b, a.c, b.c, b.d, b.f from a LEFT OUT JOIN b ON a.a = b.c
    
        7、说明:在线视图查询(表名1:a
        select * from (Select a,b,c FROM a) T where t.a > 1;
    
        8、说明:between的用法,between限制查询数据范围时包括了边界值,not between不包括
        select * from table1 where time between time1 and time2
        select a,b,c, from table1 where a not between 数值1 and 数值2
    
        9、说明:in 的使用方法
        select * from table1 where a [not] in (‘值1,’值2,’值4,’值6)
    
        10、说明:两张关联表,删除主表中已经在副表中没有的信息
        delete from table1 where not exists ( select * from table2 where table1.field1=table2.field1
    
        11、说明:四表联查问题:
        select * from a left inner join b on a.a=b.b right inner join c on a.a=c.c inner join d on a.a=d.d where ..
    
        12、说明:日程安排提前五分钟提醒
        select * from 日程安排 where datediff('minute',f开始时间,getdate())>5
    
        13、说明:一条sql 语句搞定数据库分页
        select top 10 b.* from (select top 20 主键字段,排序字段 from 表名 order by 排序字段 desc) a,表名 b where b.主键字段 = a.主键字段 order by a.排序字段
    
        14、说明:前10条记录
        select top 10 * form table1 where 范围
    
        15、说明:选择在每一组b值相同的数据中对应的a最大的记录的所有信息(类似这样的用法可以用于论坛每月排行榜,每月热销产品分析,按科目成绩排名,等等.)
        select a,b,c from tablename ta where a=(select max(a) from tablename tb where tb.b=ta.b)
    
        16、说明:包括所有在 TableA 中但不在 TableB和TableC 中的行并消除所有重复行而派生出一个结果表
        (select a from tableA   except (select a from tableB) except (select a from tableC)
    
        17、说明:随机取出10条数据
        select top 10 * from tablename order by newid()
    
        18、说明:随机选择记录
        select newid()
    
        19、说明:删除重复记录
        Delete from tablename where id not in (select max(id) from tablename group by col1,col2,)
    
        20、说明:列出数据库里所有的表名
        select name from sysobjects where type='U'
    
        21、说明:列出表里的所有的
        select name from syscolumns where id=object_id('TableName')
    
        22、说明:列示type、vender、pcs字段,以type字段排列,case可以方便地实现多重选择,类似select 中的case。
        select type,sum(case vender when 'A' then pcs else 0 end),sum(case vender when 'C' then pcs else 0 end),sum(case vender when 'B' then pcs else 0 end) 
    
    FROM tablename group by type
        显示结果:
        type vender pcs
        电脑 A 1
        电脑 A 1
        光盘 B 2
        光盘 A 2
        手机 B 3
        手机 C 3
    
        23、说明:初始化表table1
    
        TRUNCATE TABLE table1
    
        24、说明:选择从1015的记录
        select top 5 * from (select top 15 * from table order by id asc) table_别名 order by id desc
    
    三、技巧
    
        11=11=2的使用,在SQL语句组合时用的较多
    
        “where 1=1” 是表示选择全部   “where 1=2”全部不选,
        如:
        if @strWhere !='
        begin
            set @strSQL = 'select count(*) as Total from [' + @tblName + '] where ' + @strWhere
        end
        else
            begin
                set @strSQL = 'select count(*) as Total from [' + @tblName + ']'
            end
    
        我们可以直接写成
        set @strSQL = 'select count(*) as Total from [' + @tblName + '] where 1=1 安定 '+ @strWhere
    
        2、收缩数据库
        --重建索引
        DBCC REINDEX
        DBCC INDEXDEFRAG
        --收缩数据和日志
        DBCC SHRINKDB
        DBCC SHRINKFILE
    
        3、压缩数据库
        dbcc shrinkdatabase(dbname)
    
        4、转移数据库给新用户以已存在用户权限
        exec sp_change_users_login 'update_one','newname','oldname'
        go
    
        5、检查备份集
        RESTORE VERIFYONLY from disk='E:/dvbbs.bak'
    
        6、修复数据库
        Alter DATABASE [dvbbs] SET SINGLE_USER
        GO
        DBCC CHECKDB('dvbbs',repair_allow_data_loss) WITH TABLOCK
        GO
        Alter DATABASE [dvbbs] SET MULTI_USER
        GO
    
        7、日志清除
        SET NOCOUNT ON
        DECLARE @LogicalFileName sysname,
                 @MaxMinutes INT,
                 @NewSize INT
    
    
        USE     tablename             -- 要操作的数据库名
        Select   @LogicalFileName = 'tablename_log',   -- 日志文件名
        @MaxMinutes = 10,               -- Limit on time allowed to wrap log.
                 @NewSize = 1                   -- 你想设定的日志文件的大小(M)
    
        -- Setup / initialize
        DECLARE @OriginalSize int
        Select @OriginalSize = size
           FROM sysfiles
           Where name = @LogicalFileName
        Select 'Original Size of ' + db_name() + ' LOG is ' +
                 CONVERT(VARCHAR(30),@OriginalSize) + ' 8K pages or ' +
                 CONVERT(VARCHAR(30),(@OriginalSize*8/1024)) + 'MB'
           FROM sysfiles
           Where name = @LogicalFileName
        Create TABLE DummyTrans
           (DummyColumn char (8000) not null)
    
    
        DECLARE @Counter   INT,
                 @StartTime DATETIME,
                 @TruncLog   VARCHAR(255)
        Select   @StartTime = GETDATE(),
                 @TruncLog = 'BACKUP LOG ' + db_name() + ' WITH TRUNCATE_ONLY'
    
        DBCC SHRINKFILE (@LogicalFileName, @NewSize)
        EXEC (@TruncLog)
        -- Wrap the log if necessary.
        WHILE     @MaxMinutes > DATEDIFF (mi, @StartTime, GETDATE()) -- time has not expired
               AND @OriginalSize = (Select size FROM sysfiles Where name = @LogicalFileName)
               AND (@OriginalSize * 8 /1024) > @NewSize
           BEGIN -- Outer loop.
             Select @Counter = 0
             WHILE   ((@Counter < @OriginalSize / 16) AND (@Counter < 50000))
               BEGIN -- update
                 Insert DummyTrans VALUES ('Fill Log')
                 Delete DummyTrans
                 Select @Counter = @Counter + 1
               END
             EXEC (@TruncLog)
           END
        Select 'Final Size of ' + db_name() + ' LOG is ' +
                 CONVERT(VARCHAR(30),size) + ' 8K pages or ' +
                 CONVERT(VARCHAR(30),(size*8/1024)) + 'MB'
         FROM sysfiles
         Where name = @LogicalFileName
        Drop TABLE DummyTrans
        SET NOCOUNT OFF
    
        8、说明:更改某个表
        exec sp_changeobjectowner 'tablename','dbo'
    
        9、存储更改全部表
    
        Create PROCEDURE dbo.User_ChangeObjectOwnerBatch
        @OldOwner as NVARCHAR(128),
        @NewOwner as NVARCHAR(128)
        AS
    
        DECLARE @Name   as NVARCHAR(128)
        DECLARE @Owner   as NVARCHAR(128)
        DECLARE @OwnerName   as NVARCHAR(128)
    
        DECLARE curObject CURSOR FOR
        select 'Name'   = name,
           'Owner'   = user_name(uid)
        from sysobjects
        where user_name(uid)=@OldOwner
        order by name
    
        OPEN   curObject
        FETCH NEXT FROM curObject INTO @Name, @Owner
        WHILE(@@FETCH_STATUS=0)
        BEGIN
        if @Owner=@OldOwner
        begin
           set @OwnerName = @OldOwner + '.' + rtrim(@Name)
           exec sp_changeobjectowner @OwnerName, @NewOwner
        end
        -- select @name,@NewOwner,@OldOwner
    
        FETCH NEXT FROM curObject INTO @Name, @Owner
        END
    
        close curObject
        deallocate curObject
        GO
    
    
        10SQL SERVER中直接循环写入数据
        declare @i int
        set @i=1
        while @i<30
        begin
           insert into test (userid) values(@i)
           set @i=@i+1
        end 
    
    
    转载:https://blog.csdn.net/guocuifang655/article/details/3988515
    
    展开全文
  • 在互联网时代背景下,传统单一的数据库的时代已经过去,对于数据库的新需求在不断出现,随着这些新的需求越来越广泛地被提出,越来越多的企业意识到,采用传统的数据库应对不同需求这种一刀切的.

    引言

    如今,数据作为生产要素重要性已不言而喻,数据能力成为企业必不可少的核心能力之作为企业数字化转型重要的一环,我们依然迫切需要数据库来帮助存储和操作这些数据,充分有效地管理和利用各类数据资产。数据存储和操作是以业务连续性为目标,包括存储数据的设计、实现和支持活动,以及在整个数据生命周期中,从计划到销毁的各种操作活动。

    在互联网时代背景下,传统单一的数据库的时代已经过去,对于数据库的新需求在不断出现,随着这些新的需求越来越广泛地被提出,越来越多的企业意识到,采用传统的数据库应对不同需求这种一刀切的方式已经不再奏效。

    本文首先阐述了数据库和数据库管理系统的概念,并对目前常见的几种数据库进行了介绍,分析了专用数据库相比于传统数据库的优势所在,然后重点对满足不同应用场景的8种专用数据库进行了详细说明,最后分享了传统数据库向专用数据库迁移的案例,旨在帮助读者在设计应用时选择正确的数据库。

    什么是数据库?

    1.1

    数据库概念

    维基百科上对数据库的定义:以一定方式储存在一起、能予多个用户共享、具有尽可能小的冗余度、与应用程序彼此独立的数据集合。一个数据库由多个表空间构成。

    百度百科上对数据库的定义:是“按照数据结构来组织、存储和管理数据的仓库”。是一个长期存储在计算机内的、有组织的、可共享的、统一管理的大量数据的集合。

    数据库(Database,英文简称 DB)是一个以某种有组织的方式存储的数据集合。可以理解为是一个存放计算机数据的仓库,这个仓库按照一定的数据结构(即数据的组织形式或数据之间的联系)来对数据进行组织和存储,我们可以通过数据库提供的多种方法来管理其中的数据。

    1.2

    数据库管理系统

    数据库管理系统(Database ManagementSystem,英文简称DBMS)是为管理数据库而设计的电脑软件系统,是一种系统软件,负责数据库中的数据组织、数据操作、数据维护、控制及保护和数据服务。数据库管理系统是数据系统的核心,主要功能有:数据模式定义、数据存取的物理构建、数据操纵、数据的完整性、安全性定义和检查、数据库的并发控制与故障恢复、数据的服务。我们常见的数据管理系统如:Oracle、SQL Server、MySQL、Accees、Sybase、DB2等。

    1.3

    数据库和数据库管理系统的关系

    数据库和数据库管理系统在IT软件中扮演着不可或缺的角色。比如某公司建设了员工管理系统,员工的信息都会存放在数据库中。当登录员工管理系统查询某员工的工资信息时,部署在服务器上的程序会连接数据库管理系统进行查询,并从数据库中取出该员工的工资数据,最后显示到前端系统页面上。

    查询数据的过程

    数据库种类及应用场景介绍

    一般来说,数据库按照组织式分为两大类:关系型数据库和非关系型数据库。

    1.关系型数据库是把复杂的数据结构归结为简单的二元关系(即二维表格形式)。在关系型数据库中,对数据的操作几乎全部建立在一个或多个关系表格上,通过这些关联的表格分类、合并、连接或选取等运算来实现数据的管理。

    2.非关系型数据库又称NoSQL,由于数据类型多种多样,关系型数据库并不适用于所有的数据,因此针对不同的数据类型,出现了不同的 NoSQL,NoSQL的产生并不是要彻底否定关系型数据库,而是作为传统数据库的有效补充。

    关系型SQL与非关系型NoSQL对比表

    注:关系型数据库的ACID:

    A (Atomicity) 原子性:就是说事务里的所有操作要么全部做完,要么都不做,事务成功的条件是事务里的所有操作都成功,只要有一个操作失败,整个事务就失败,需要回滚。比如银行转账,从A账户转5元至B账户,分为两个步骤:从A账户取5元;存入5元至B账户。这两步要么一起完成,要么一起不完成,如果只完成第一步,第二步失败,钱会莫名其妙少了5元。

    C (Consistency) 一致性:一致性也比较容易理解,也就是说数据库要一直处于一致的状态,事务的运行不会改变数据库原本的一致性约束。例如现有完整性约束a+b=10,如果一个事务改变了a,那么必须得改变b,使得事务结束后依然满足a+b=10,否则事务失败。

    I (Isolation) 独立性:是指并发的事务之间不会互相影响,如果一个事务要访问的数据正在被另外一个事务修改,只要另外一个事务未提交,它所访问的数据就不受未提交事务的影响。例如:现有有个交易是从A账户转5元至B账户,在这个交易还未完成的情况下,如果此时B查询自己的账户,是看不到新增加的5元的。

    D (Durability) 持久性:指一旦事务提交后,它所做的修改将会永久的保存在数据库上,即使出现宕机也不会丢失。

    CAP理论的C就是一致性(Consistency),A就是可用性(availability),可以理解为是否可获取数据,以及获取数据的速度;P就是分区容忍度(partion tolerance),指的是系统中的数据分布性的大小对系统的正确性,性能的影响(一定程度上就是可扩展性)。

    2.1

    关系数据库

    关系数据库是使用最广泛的数据库,采用了关系模型来组织数据的数据库,其以行和列的形式存储数据,以便于用户理解,关系型数据库这一系列的行和列被称为表,一组表组成了数据库。主要结构为:库+表+表之间的关系+字段。

    关系数据库表示例表

    关系数据库把复杂的数据结构归结为简单的二元关系(二维表),如上图所示是一个二维表的示例,通常该表第一行为字段名称,描述该字段的作用,下面是具体的数据。在定义该表时需要指定字段的名称及类型。目前主流的关系型数据库有OracleL、SQL Server、DB2、MySQL、PostgreSQL等。

    2.2

    非关系数据库

    常见的非关系型数据库有键值数据库、列存储数据库、文档数据库、图数据库、时序数据库、搜索引擎数据库等,这些常见数据库的主要特点及应用场景如下表所示。

    几种常见非关系数据库的主要特点及应用场景

    2.2.1 键值数据库

    键值数据库可以被看作一个非常大的哈希表,该表在唯一的键下存储了一些值。存储的值可以通过键或者部分键高效地检索到。键值数据库使用简单的键值方法来存储数据。键值数据库将数据存储为键值对集合,其中键作为唯一标识符。键值数据库中的键可以包含多个元素,甚至可以排序以提高查询效率。一些键值数据库允许使用键的前缀进行查找,从而可以使用复合键。 

    例如,我们将客户ABC的订单存储在键/值数据库中,可以使用客户ID作为键的前缀,结合订单号组成键“ABC-001”来存储订单。可以使用整个键来检索特定的订单,也可以使用“ABC”前缀检索客户ABC的所有订单。

    2.2.2 列存储数据库

    列存储数据库又被称为面向可扩展性的分布式数据库,它反转了传统的行存储数据库,将数据存储存在列族中,一个列族存储经常被一起查询的相关数据。如下表所示为人员信息表:

    对于行存储数据库,表中的数据是以行为单位逐行存储在磁盘上的;而对于列存储数据库,表中的数据则是以列为单位逐列存储在磁盘中。下图是传统行数据库和列数据库表中数据在磁盘上的存储形式的差异对比。

    列存储解决的主要问题是数据查询问题,这部分数据库通常用来应对分布式存储的海量数据,典型的产品应用如Hbase。

    2.2.3 文档数据库

    文档数据库是一种非关系数据库,将半结构化数据存储为文档,其中文档包括 XML、YAML、JSON、BSON、office 文档等不同格式。文档型数据库可以看作是键值数据库的升级版,允许之间嵌套键值。

    简而言之,就是将数据保存到以上类似格式的文档中,数据库中的每个记录都是以文档形式存在的,相互之间不再存在关联关系。文档数据库所存放的文档,就相当于键值数据库所存放的“值”。

    2.2.4 图数据库

    图数据库顾名思义,就是一种存储图形关系的数据库,而图模型是图数据库中的重要概念。图模型由两个要素组成:节点和边,每个节点代表一个实体(人、地点、事物等),每条边代表两个节点之间的连接,这种通用结构可以对各种场景进行建模,如社交网络以及由关系定义的任何其他事物。

    如下所示的图模型中包含 3个节点:中国、北京、长城。其两条边分别是:长城是北京的著名景点、北京属于中国。

    从上面的图模型可以看出,图数据库的目标就是基于图模型以一种直观的方式模拟这些关系,可以很好地分析实体之间的关系。

    2.2.5 时序数据库

    在介绍时序数据库前先了解下时序数据,时序数据是按照时间顺序记录系统、设备状态变化的数据,普遍存在于IT基础设施、运维监控系统和物联网中。在有时间的坐标中将这些数据点连成线,往前看可以做成多纬度报表,揭示其趋势性、规律性、异常性;往后看可以建立数学模型、做统计分析,预测事物发展趋势。

    时序数据库就是存放时序数据的数据库,并且需要支持时序数据的快速写入、持久化、多纬度的聚合查询等基本功能。相比于传统数据库仅仅记录了数据的当前值,时序数据库则记录了所有的历史数据。同时时序数据的查询也总是会带上时间作为过滤条件。

     

    下面对时序数据库的数学模型做下简单介绍:

    • metric:度量的数据集,类似于关系型数据库中的table

    • point:一个数据点,类似于关系型数据库中的row

    • timestamp:时间戳,表征采集到数据的时间点

    • tag:维度列,代表数据的归属、属性,表明是哪个设备/模块产生的,一般不随着时间变化,供查询使用

    • field:指标列,代表数据的测量值,随时间平滑波动,不需要查询

    时序数据库基本概念图

    如上表中,度量为Wind,每一个数据点都具有一个timestamp,其中有两个field:风向、速度,两个tag:设备编号、城市。根据表中第一行和第三行的数据可知,存放的都是sensor号码为95D8-791的设备,属性城市是北京。随着时间的变化,风向和风速都发生了变化,风向从24.2变成25.6,风速从3.6变成了3.3。

    2.2.6 搜索引擎数据库

    搜索引擎数据库通常用于搜索保存在其他存储和服务中的数据。搜索引擎数据库可以对大量的数据建立索引,并提供近实时的索引查询。搜索引擎数据库是应用在搜索引擎领域的数据存储形式,由于搜索引擎会爬取大量的数据,并以特定的格式进行存储,这样在检索的时候才能保证性能最优。

    搜索引擎数据库除了搜索像网页这样的非结构化的数据,许多应用程序还使用它为其他数据库中的数据提供结构化和即时搜索功能。有一些数据库也能提供全文索引功能,但是搜索数据库还具备通过词干和泛化将单词缩减为词根的功能。

    三 为什么越来越多的企业选择专用数据库?

    “原来数据库分发方式是怎么样的?一家企业要买数据库,比如Oracle,首先要买一年或者两年的授权,第二要买跑数据库的硬件,第三还得买数据库相关的服务,包括固件更新、维护升级等等。传统的数据库购买流程是一个非常沉重的过程,投入会非常大”,相信很多IT从业人员对这句话深有感触。传统商用数据库是集中式架构,在扩展性和灵活上先天不足,比如传统的商业数据库可能仅仅软件安装就需要一整天的时间,需要配置各种补丁等,需要有专业的DBA(数据库管理员)来完成这样的服务,如果需要扩展通常只能是纵向扩展,为此需要购买昂贵的设备,投资不菲。

    传统数据库架构面向早期业务模型,包括传统数据库的售卖方式、使用方式、服务方式,在数字化的背景和海量数据存储的诉求下,已经不能满足大多数企业的诉求。从技术角度来看,云计算已经发展到非常成熟的阶段,并且被广泛认可,云计算由量变到质变的过程,给数据库带来了颠覆,核心是云计算彻底改变了数据库的分发方式。

    专用数据库相比于传统数据库在成本、安全性、操作及效率4个方面具有更适应现代IT技术快速发展的优势:

    传统数据库VS专用数据库

    可以看到,在实际业务运营过程中有各种不同的数据管理需求的时候,就需要迁移到专用的数据库来。自我管理的这些数据库和分析服务,因为耗时、管理起来复杂性很高,尤其是硬件、软件的安装,同时数据库的性能、可用性又遇到很多的挑战,又不像在云上那么容易的进行扩展。那么迁移到专用数据库有什么好处呢?下图为在AWS上的全托管服务和自己管理的区别。

    自我管理与AWS完全托管的区别

    全托管的服务之下,对于用户来说,只需要去关注几个事情:应用层的架构设计、采用什么样的数据库、解决什么样的场景问题、查询构造、怎么去优化SQL查询语句或是NoSQL的查询方式。剩下的与数据库本身相关的工作,比如故障的转移、备份和恢复、隔离和安全、行业合规、补丁修复、监控、维护等,都可以交给AWS来做。这样一来,用户可以更加专注于业务本身的创新,而不是把时间浪费在数据库这种非常耗时、耗精力的基本维护上。

    展开全文
  • 五个常见 PHP 数据库问题 以及如何避免这些问题 级别: 中级

    五个常见 PHP 数据库问题

    以及如何避免这些问题

    developerWorks

    级别: 中级

    Jack Herrington (jherr@pobox.com), 高级软件工程师, Studio B

    2006 年 10 月 08 日

    揭露 PHP 应用程序中出现的五个常见数据库问题 —— 包括数据库模式设计、数据库访问和使用数据库的业务逻辑代码 —— 以及它们的解决方案。

    如果只有一种 方式使用数据库是正确的……

    您可以用很多的方式创建数据库设计、数据库访问和基于数据库的 PHP 业务逻辑代码,但最终一般以错误告终。本文说明了数据库设计和访问数据库的 PHP 代码中出现的五个常见问题,以及在遇到这些问题时如何修复它们。

    问题 1:直接使用 MySQL

    一个常见问题是较老的 PHP 代码直接使用 mysql_ 函数来访问数据库。清单 1 展示了如何直接访问数据库。


    清单 1. Access/get.php
    <?php
    function get_user_id( $name )
    {
      $db = mysql_connect( 'localhost', 'root', 'password' );
      mysql_select_db( 'users' );
    
      $res = mysql_query( "SELECT id FROM users WHERE login='".$name."'" );
      while( $row = mysql_fetch_array( $res ) ) { $id = $row[0]; }
    
      return $id;
    }
    
    var_dump( get_user_id( 'jack' ) );
    ?>
    

    注意使用了 mysql_connect 函数来访问数据库。还要注意查询,其中使用字符串连接来向查询添加 $name 参数。

    该技术有两个很好的替代方案:PEAR DB 模块和 PHP Data Objects (PDO) 类。两者都从特定数据库选择提供抽象。因此,您的代码无需太多调整就可以在 IBM® DB2®、MySQL、PostgreSQL 或者您想要连接到的任何其他数据库上运行。

    使用 PEAR DB 模块和 PDO 抽象层的另一个价值在于您可以在 SQL 语句中使用 ? 操作符。这样做可使 SQL 更加易于维护,且可使您的应用程序免受 SQL 注入攻击。

    使用 PEAR DB 的替代代码如下所示。


    清单 2. Access/get_good.php
    <?php
    require_once("DB.php");
    
    function get_user_id( $name )
    {
      $dsn = 'mysql://root:password@localhost/users';
      $db =& DB::Connect( $dsn, array() );
      if (PEAR::isError($db)) { die($db->getMessage()); }
    
      $res = $db->query( 'SELECT id FROM users WHERE login=?',
      array( $name ) );
      $id = null;
      while( $res->fetchInto( $row ) ) { $id = $row[0]; }
    
      return $id;
    }
    
    var_dump( get_user_id( 'jack' ) );
    ?>
    

    注意,所有直接用到 MySQL 的地方都消除了,只有 $dsn 中的数据库连接字符串除外。此外,我们通过 ? 操作符在 SQL 中使用 $name 变量。然后,查询的数据通过 query() 方法末尾的 array 被发送进来。





    回页首


    问题 2:不使用自动增量功能

    与大多数现代数据库一样,MySQL 能够在每记录的基础上创建自动增量惟一标识符。除此之外,我们仍然会看到这样的代码,即首先运行一个 SELECT 语句来找到最大的 id,然后将该 id 增 1,并找到一个新记录。清单 3 展示了一个示例坏模式。


    清单 3. Badid.sql
    DROP TABLE IF EXISTS users;
    CREATE TABLE users (
      id MEDIUMINT,
      login TEXT,
      password TEXT
    );
    
    INSERT INTO users VALUES ( 1, 'jack', 'pass' );
    INSERT INTO users VALUES ( 2, 'joan', 'pass' );
    INSERT INTO users VALUES ( 1, 'jane', 'pass' );
    

    这里的 id 字段被简单地指定为整数。所以,尽管它应该是惟一的,我们还是可以添加任何值,如 CREATE 语句后面的几个 INSERT 语句中所示。清单 4 展示了将用户添加到这种类型的模式的 PHP 代码。


    清单 4. Add_user.php
    <?php
    require_once("DB.php");
    
    function add_user( $name, $pass )
    {
      $rows = array();
    
      $dsn = 'mysql://root:password@localhost/bad_badid';
      $db =& DB::Connect( $dsn, array() );
      if (PEAR::isError($db)) { die($db->getMessage()); }
    
      $res = $db->query( "SELECT max(id) FROM users" );
      $id = null;
      while( $res->fetchInto( $row ) ) { $id = $row[0]; }
    
      $id += 1;
    
      $sth = $db->prepare( "INSERT INTO users VALUES(?,?,?)" );
      $db->execute( $sth, array( $id, $name, $pass ) );
    
      return $id;
    }
    
    $id = add_user( 'jerry', 'pass' );
    
    var_dump( $id );
    ?>
    

    add_user.php 中的代码首先执行一个查询以找到 id 的最大值。然后文件以 id 值加 1 运行一个 INSERT 语句。该代码在负载很重的服务器上会在竞态条件中失败。另外,它也效率低下。

    那么替代方案是什么呢?使用 MySQL 中的自动增量特性来自动地为每个插入创建惟一的 ID。更新后的模式如下所示。


    清单 5. Goodid.php
    DROP TABLE IF EXISTS users;
    CREATE TABLE users (
      id MEDIUMINT NOT NULL AUTO_INCREMENT,
      login TEXT NOT NULL,
      password TEXT NOT NULL,
      PRIMARY KEY( id )
    );
    
    INSERT INTO users VALUES ( null, 'jack', 'pass' );
    INSERT INTO users VALUES ( null, 'joan', 'pass' );
    INSERT INTO users VALUES ( null, 'jane', 'pass' );
    

    我们添加了 NOT NULL 标志来指示字段必须不能为空。我们还添加了 AUTO_INCREMENT 标志来指示字段是自动增量的,添加 PRIMARY KEY 标志来指示那个字段是一个 id。这些更改加快了速度。清单 6 展示了更新后的 PHP 代码,即将用户插入表中。


    清单 6. Add_user_good.php
    <?php
    require_once("DB.php");
    
    function add_user( $name, $pass )
    {
      $dsn = 'mysql://root:password@localhost/good_genid';
      $db =& DB::Connect( $dsn, array() );
      if (PEAR::isError($db)) { die($db->getMessage()); }
    
      $sth = $db->prepare( "INSERT INTO users VALUES(null,?,?)" );
      $db->execute( $sth, array( $name, $pass ) );
    
      $res = $db->query( "SELECT last_insert_id()" );
      $id = null;
      while( $res->fetchInto( $row ) ) { $id = $row[0]; }
    
      return $id;
    }
    
    $id = add_user( 'jerry', 'pass' );
    
    var_dump( $id );
    ?>
    

    现在我不是获得最大的 id 值,而是直接使用 INSERT 语句来插入数据,然后使用 SELECT 语句来检索最后插入的记录的 id。该代码比最初的版本及其相关模式要简单得多,且效率更高。





    回页首


    问题 3:使用多个数据库

    偶尔,我们会看到一个应用程序中,每个表都在一个单独的数据库中。在非常大的数据库中这样做是合理的,但是对于一般的应用程序,则不需要这种级别的分割。此外,不能跨数据库执行关系查询,这会影响使用关系数据库的整体思想,更不用说跨多个数据库管理表会更困难了。

    那么,多个数据库应该是什么样的呢?首先,您需要一些数据。清单 7 展示了分成 4 个文件的这样的数据。


    清单 7. 数据库文件
    Files.sql:
    CREATE TABLE files (
      id MEDIUMINT,
      user_id MEDIUMINT,
      name TEXT,
      path TEXT
    );
    
    Load_files.sql:
    INSERT INTO files VALUES ( 1, 1, 'test1.jpg', 'files/test1.jpg' );
    INSERT INTO files VALUES ( 2, 1, 'test2.jpg', 'files/test2.jpg' );
    
    Users.sql:
    DROP TABLE IF EXISTS users;
    CREATE TABLE users (
      id MEDIUMINT,
      login TEXT,
      password TEXT
    );
    
    Load_users.sql:
    INSERT INTO users VALUES ( 1, 'jack', 'pass' );
    INSERT INTO users VALUES ( 2, 'jon', 'pass' );
    

    在这些文件的多数据库版本中,您应该将 SQL 语句加载到一个数据库中,然后将 users SQL 语句加载到另一个数据库中。用于在数据库中查询与某个特定用户相关联的文件的 PHP 代码如下所示。


    清单 8. Getfiles.php
    <?php
    require_once("DB.php");
    
    function get_user( $name )
    {
      $dsn = 'mysql://root:password@localhost/bad_multi1';
      $db =& DB::Connect( $dsn, array() );
      if (PEAR::isError($db)) { die($db->getMessage()); }
    
      $res = $db->query( "SELECT id FROM users WHERE login=?",
      array( $name ) );
      $uid = null;
      while( $res->fetchInto( $row ) ) { $uid = $row[0]; }
    
      return $uid;
    }
    
    function get_files( $name )
    {
      $uid = get_user( $name );
    
      $rows = array();
    
      $dsn = 'mysql://root:password@localhost/bad_multi2';
      $db =& DB::Connect( $dsn, array() );
      if (PEAR::isError($db)) { die($db->getMessage()); }
    
      $res = $db->query( "SELECT * FROM files WHERE user_id=?",
      array( $uid ) );
      while( $res->fetchInto( $row ) ) { $rows[] = $row; }
    
      return $rows;
    }
    
    $files = get_files( 'jack' );
    
    var_dump( $files );
    ?>
    

    get_user 函数连接到包含用户表的数据库并检索给定用户的 ID。get_files 函数连接到文件表并检索与给定用户相关联的文件行。

    做所有这些事情的一个更好办法是将数据加载到一个数据库中,然后执行查询,比如下面的查询。


    清单 9. Getfiles_good.php
    <?php
    require_once("DB.php");
    
    function get_files( $name )
    {
      $rows = array();
    
      $dsn = 'mysql://root:password@localhost/good_multi';
      $db =& DB::Connect( $dsn, array() );
      if (PEAR::isError($db)) { die($db->getMessage()); }
    
      $res = $db->query(
      "SELECT files.* FROM users, files WHERE
      users.login=? AND users.id=files.user_id",
      array( $name ) );
      while( $res->fetchInto( $row ) ) { $rows[] = $row; }
    
      return $rows;
    }
    
    $files = get_files( 'jack' );
    
    var_dump( $files );
    ?>
    

    该代码不仅更短,而且也更容易理解和高效。我们不是执行两个查询,而是执行一个查询。

    尽管该问题听起来有些牵强,但是在实践中我们通常总结出所有的表应该在同一个数据库中,除非有非常迫不得已的理由。





    回页首


    问题 4:不使用关系

    关系数据库不同于编程语言,它们不具有数组类型。相反,它们使用表之间的关系来创建对象之间的一到多结构,这与数组具有相同的效果。我在应用程序中看到的一个问题是,工程师试图将数据库当作编程语言来使用,即通过使用具有逗号分隔的标识符的文本字符串来创建数组。请看下面的模式。


    清单 10. Bad.sql
    DROP TABLE IF EXISTS files;
    CREATE TABLE files (
      id MEDIUMINT,
      name TEXT,
      path TEXT
    );
    
    DROP TABLE IF EXISTS users;
    CREATE TABLE users (
      id MEDIUMINT,
      login TEXT,
      password TEXT,
      files TEXT
    );
    
    INSERT INTO files VALUES ( 1, 'test1.jpg', 'media/test1.jpg' );
    INSERT INTO files VALUES ( 2, 'test1.jpg', 'media/test1.jpg' );
    INSERT INTO users VALUES ( 1, 'jack', 'pass', '1,2' );
    

    系统中的一个用户可以具有多个文件。在编程语言中,应该使用数组来表示与一个用户相关联的文件。在本例中,程序员选择创建一个 files 字段,其中包含一个由逗号分隔的文件 id 列表。要得到一个特定用户的所有文件的列表,程序员必须首先从用户表中读取行,然后解析文件的文本,并为每个文件运行一个单独的 SELECT 语句。该代码如下所示。


    清单 11. Get.php
    <?php
    require_once("DB.php");
    
    function get_files( $name )
    {
      $dsn = 'mysql://root:password@localhost/bad_norel';
      $db =& DB::Connect( $dsn, array() );
      if (PEAR::isError($db)) { die($db->getMessage()); }
    
      $res = $db->query( "SELECT files FROM users WHERE login=?",
      array( $name ) );
      $files = null;
      while( $res->fetchInto( $row ) ) { $files = $row[0]; }
    
      $rows = array();
    
      foreach( split( ',',$files ) as $file )
      {
        $res = $db->query( "SELECT * FROM files WHERE id=?",
          array( $file ) );
        while( $res->fetchInto( $row ) ) { $rows[] = $row; }
      }
    
      return $rows;
    }
    
    $files = get_files( 'jack' );
    
    var_dump( $files );
    ?>
    

    该技术很慢,难以维护,且没有很好地利用数据库。惟一的解决方案是重新架构模式,以将其转换回到传统的关系形式,如下所示。


    清单 12. Good.sql
    DROP TABLE IF EXISTS files;
    CREATE TABLE files (
      id MEDIUMINT,
      user_id MEDIUMINT,
      name TEXT,
      path TEXT
    );
    
    DROP TABLE IF EXISTS users;
    CREATE TABLE users (
      id MEDIUMINT,
      login TEXT,
      password TEXT
    );
    
    INSERT INTO users VALUES ( 1, 'jack', 'pass' );
    INSERT INTO files VALUES ( 1, 1, 'test1.jpg', 'media/test1.jpg' );
    INSERT INTO files VALUES ( 2, 1, 'test1.jpg', 'media/test1.jpg' );
    

    这里,每个文件都通过 user_id 函数与文件表中的用户相关。这可能与任何将多个文件看成数组的人的思想相反。当然,数组不引用其包含的对象 —— 事实上,反之亦然。但是在关系数据库中,工作原理就是这样的,并且查询也因此要快速且简单得多。清单 13 展示了相应的 PHP 代码。


    清单 13. Get_good.php
    <?php
    require_once("DB.php");
    
    function get_files( $name )
    {
      $dsn = 'mysql://root:password@localhost/good_rel';
      $db =& DB::Connect( $dsn, array() );
      if (PEAR::isError($db)) { die($db->getMessage()); }
    
      $rows = array();
      $res = $db->query(
        "SELECT files.* FROM users,files WHERE users.login=?
          AND users.id=files.user_id",
            array( $name ) );
      while( $res->fetchInto( $row ) ) { $rows[] = $row; }
    
      return $rows;
    }
    
    $files = get_files( 'jack' );
    
    var_dump( $files );
    ?>
    

    这里,我们对数据库进行一次查询,以获得所有的行。代码不复杂,并且它将数据库作为其原有的用途使用。





    回页首


    问题 5:n+1 模式

    我真不知有多少次看到过这样的大型应用程序,其中的代码首先检索一些实体(比如说客户),然后来回地一个一个地检索它们,以得到每个实体的详细信息。我们将其称为 n+1 模式,因为查询要执行这么多次 —— 一次查询检索所有实体的列表,然后对于 n 个实体中的每一个执行一次查询。当 n=10 时这还不成其为问题,但是当 n=100 或 n=1000 时呢?然后肯定会出现低效率问题。清单 14 展示了这种模式的一个例子。


    清单 14. Schema.sql
    DROP TABLE IF EXISTS authors;
    CREATE TABLE authors (
      id MEDIUMINT NOT NULL AUTO_INCREMENT,
      name TEXT NOT NULL,
      PRIMARY KEY ( id )
    );
    
    DROP TABLE IF EXISTS books;
    CREATE TABLE books (
      id MEDIUMINT NOT NULL AUTO_INCREMENT,
      author_id MEDIUMINT NOT NULL,
      name TEXT NOT NULL,
      PRIMARY KEY ( id )
    );
    
    INSERT INTO authors VALUES ( null, 'Jack Herrington' );
    INSERT INTO authors VALUES ( null, 'Dave Thomas' );
    
    INSERT INTO books VALUES ( null, 1, 'Code Generation in Action' );
    INSERT INTO books VALUES ( null, 1, 'Podcasting Hacks' );
    INSERT INTO books VALUES ( null, 1, 'PHP Hacks' );
    INSERT INTO books VALUES ( null, 2, 'Pragmatic Programmer' );
    INSERT INTO books VALUES ( null, 2, 'Ruby on Rails' );
    INSERT INTO books VALUES ( null, 2, 'Programming Ruby' );
    

    该模式是可靠的,其中没有任何错误。问题在于访问数据库以找到一个给定作者的所有书籍的代码中,如下所示。


    清单 15. Get.php
    <?php
    require_once('DB.php');
    
    $dsn = 'mysql://root:password@localhost/good_books';
    $db =& DB::Connect( $dsn, array() );
    if (PEAR::isError($db)) { die($db->getMessage()); }
    
    function get_author_id( $name )
    {
      global $db;
    
      $res = $db->query( "SELECT id FROM authors WHERE name=?",
        array( $name ) );
      $id = null;
      while( $res->fetchInto( $row ) ) { $id = $row[0]; }
      return $id;
    }
    
    function get_books( $id )
    {
      global $db;
    
      $res = $db->query( "SELECT id FROM books WHERE author_id=?",
        array( $id ) );
      $ids = array();
      while( $res->fetchInto( $row ) ) { $ids []= $row[0]; }
      return $ids;
    }
    
    function get_book( $id )
    {
      global $db;
    
      $res = $db->query( "SELECT * FROM books WHERE id=?", array( $id ) );
      while( $res->fetchInto( $row ) ) { return $row; }
      return null;
    }
    
    $author_id = get_author_id( 'Jack Herrington' );
    $books = get_books( $author_id );
    foreach( $books as $book_id ) {
      $book = get_book( $book_id );
      var_dump( $book );
    }
    ?>
    

    如果您看看下面的代码,您可能会想,“嘿,这才是真正的清楚明了。” 首先,得到作者 id,然后得到书籍列表,然后得到有关每本书的信息。的确,它很清楚明了,但是其高效吗?回答是否定的。看看只是检索 Jack Herrington 的书籍时要执行多少次查询。一次获得 id,另一次获得书籍列表,然后每本书执行一次查询。三本书要执行五次查询!

    解决方案是用一个函数来执行大量的查询,如下所示。


    清单 16. Get_good.php
    <?php
    require_once('DB.php');
    
    $dsn = 'mysql://root:password@localhost/good_books';
    $db =& DB::Connect( $dsn, array() );
    if (PEAR::isError($db)) { die($db->getMessage()); }
    
    function get_books( $name )
    {
      global $db;
    
      $res = $db->query(
        "SELECT books.* FROM authors,books WHERE
          books.author_id=authors.id AND authors.name=?",
          array( $name ) );
      $rows = array();
      while( $res->fetchInto( $row ) ) { $rows []= $row; }
      return $rows;
    }
    
    $books = get_books( 'Jack Herrington' );
    var_dump( $books );
    ?>
    

    现在检索列表需要一个快速、单个的查询。这意味着我将很可能必须具有几个这些类型的具有不同参数的方法,但是实在是没有选择。如果您想要具有一个扩展的 PHP 应用程序,那么必须有效地使用数据库,这意味着更智能的查询。

    本例的问题是它有点太清晰了。通常来说,这些类型的 n+1n*n 问题要微妙得多。并且它们只有在数据库管理员在系统具有性能问题时在系统上运行查询剖析器时才会出现。





    回页首


    结束语

    数据库是强大的工具,就跟所有强大的工具一样,如果您不知道如何正确地使用就会滥用它们。识别和解决这些问题的诀窍是更好地理解底层技术。长期以来,我老听到业务逻辑编写人员抱怨,他们不想要必须理解数据库或 SQL 代码。他们把数据库当成对象使用,并疑惑性能为什么如此之差。

    他们没有认识到,理解 SQL 对于将数据库从一个困难的必需品转换成强大的联盟是多么重要。如果您每天使用数据库,但是不熟悉 SQL,那么请阅读 The Art of SQL,这本书写得很好,实践性也很强,可以指导您基本了解数据库。



    参考资料

    学习
    • 您可以参阅本文在 developerWorks 全球站点上的 英文原文

    • Stephane Faroult 和 Peter Robson 编写的 The Art of SQL 对于在其应用程序中使用数据库的程序员来说是必读书籍。

    • PHP.net 是学习 PHP 的起点。

    • PEAR DB 文档 是一个很好的资源。

    • PDO Functions 文档 可以帮助您快速掌握 PHP Data Objects (PDO)。

    • MySQL.org 具有优秀的文档,其中的例子展示了如何更好地使用数据库。

    • 访问 IBM developerWorks 的 PHP 项目资源,更多地了解 PHP。

    • 随时关注 developerWorks 技术事件和网络广播

    • 检查世界各地即将到来的与 IBM 开放源码开发人员有关的会议、贸易展会、网络广播和其他 事件

    • 访问 developerWorks 开放源码专区,获得广泛的 how-to 信息、工具和项目更新,帮助您利用开放源码技术进行开发,并将它们与 IBM 产品结合使用。

    • 要聆听对软件开发人员有兴趣的访谈和讨论,请检查 developerWorks podcasts


    获得产品和技术
    • IBM 试用软件 革新您的下一个开放源码开发项目,这些软件可通过下载或 DVD 获得。


    讨论


    关于作者

     

    Jack D. Herrington 是一名具有 20 多年经验的高级软件工程师。他编写了 3 本书:Code Generation in Action、Podcasting HacksPHP Hacks。他还撰写过 30 多篇文章。

     
    展开全文
  • 数据库面试常见问题

    千次阅读 2017-11-22 14:51:29
    数据库面试常见问题
  • 常见数据库的简介

    2015-09-15 09:27:40
    一 几种常见数据库及其发展历史 1. IBM 的DB2  作为关系数据库领域的开拓者和领航人,IBM在1977年完成了System R系统的原型,1980年开始提供集成的数据库服务器—— System/38,随后是SQL/DSforVSE和VM,其...
  • 如果必1. 解释冷备份和热备份的不同点以及各自的优点解答:热备份针对归档模式的数据库,在数据库仍旧处于工作状态时进行备份。而冷备份指在数据库关闭后,,进行备份,适用于所有模式的数据库。热备份的优点在于...
  • 解答:热备份针对归档模式的数据库,在数据库仍旧处于工作状态时进行备份。而冷备份指在数据库关闭后,进行备份,适用于所有模式的数据库。热备份的优点在于当备份时,数据库仍旧可以被使用并且可以将数据库恢复到...
  • 数据库常见面试题

    千次阅读 2020-02-11 14:32:11
    原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。 一致性(Consistency) 事务开始前和结束后,数据库的...
  • 数据库常见问题

    2019-08-08 11:20:26
    数据库常见问题 一、数据库是什么 1.为什么会有数据库 平常我们在存储的时候大多使用的是文件,但是文件存储不利于我们进行查询、也不利于我们存储大量的数据,安全性也不能保证,所以我们数据库 2.是什么 ...
  • MySQL 数据库常见操作

    2015-05-05 10:51:30
    MySQL 数据库常见操作
  • 数据库

    2020-12-14 18:16:07
    数据库:英文为Databsae,简称DB 数据库是按照数据结构来组织,存储和管理数据的仓库 简而言之,数据库就是*存储数据的仓库* 2.数据库的分类 数据库根据句存储采用的数据结构的不同可以分为许多种,其中包含早期的*...
  • 数据库常见笔试题

    万次阅读 2016-11-17 17:41:38
    数据库基础(面试常见题) 一、数据库基础 1. 数据抽象:物理抽象、概念抽象、视图级抽象,内模式、模式、外模式 2. SQL语言包括数据定义、数据操纵(Data Manipulation),数据控制(Data Control) 数据定义:Create ...
  • 数据库操作常见错误

    2020-05-17 22:36:58
    数据操作常见错误 检查SQL Server服务器是否打开 检查连接字符串中服务器关键字指定的服务器名称是否正确(注意默认实例、命名实例的名称) 如果连接的是局域网内服务器、外网服务器(非本地连接)。检查...
  • 英语来说,数据库管理系统(DBMS)是一个程序,可以帮助用户创建和维护数据库: 它助于处理大量信息。 管理安全性问题(访问控制)。 允许您进行备份。 您可以导入和导出数据。 与软件应用程序的交互。 增...
  • 关系型数据库 关系型数据库 (MySQL、Oracle、PostgreSQL、Microsoft Access、Microsoft SQL Server、Google Fusion Tables、FileMaker、Sybase、dBASE、Clipper、FoxPro、foshub、Percona Server...英文维基百科...
  • 数据库设计常见错误

    千次阅读 2016-05-13 12:01:09
    如果你想学习设计数据库,一定得一些理论背景,比如关于数据库设计范式和事务隔离级别的知识。但你还应该尽可能地多加练习,因为可悲的事实就是,我们在犯错中学习得更多。 本文中,通过展示在设计数据库时常犯...
  • 数据库常见笔试面试题

    万次阅读 多人点赞 2013-10-31 10:17:47
    数据库基础(面试常见题) 一、数据库基础 1. 数据抽象:物理抽象、概念抽象、视图级抽象,内模式、模式、外模式 2. SQL语言包括数据定义、数据操纵(Data Manipulation),数据控制(Data Control) 数据定义:Create ...
  • 除非是常规方法不能解决的~下面是常见安装插件会出现的数据库错误信息提示:[Copy to clipboard]CODE:Duplicate column name allowrank升级数据偶尔这样吧,表示这个表已经存在。但是如果是安装的话不影响下面
  • 数据库常见的面试题

    千次阅读 2016-05-29 00:14:31
    遇到的困难是:PL/SQL居多,T-SQL太少,所以需要筛选,修改答案,甚至一些在T-SQL里面还没有支持。 下一步再把数据库T-SQL经典教程在翻看一遍,基本上对数据库就算告一段落了,前前后后共整整1个多月的时间...
  • 数据库索引常见四种类型

    万次阅读 2019-03-19 12:53:34
    索引分四类: index ----普通的索引,数据可以重复 fulltext----全文索引,用来对大表的文本域(char,varchar,text)进行索引。语法和普通索引一样。 unique ----唯一索引,唯一索引,要求所有记录都唯一 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 87,209
精华内容 34,883
关键字:

常见的英文数据库有哪些