数据库的多表大数据查询应如何优化

数据库的多表大数据查询应如何优化,第1张

数据库的多表大数据查询应如何优化?

1应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:

select id from t where num is null

可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:

select id from t where num=0

2应尽量避免在 where 子句中使用!=或<> *** 作符,否则将引擎放弃使用索引而进行全表扫描。优化器将无法通过索引来确定将要命中的行数,因此需要搜索该表的所有行。

3应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如:

select id from t where num=10 or num=20

可以这样查询:

select id from t where num=10

union all

select id from t where num=20

4in 和 not in 也要慎用,因为IN会使系统无法使用索引,而只能直接搜索表中的数据。如:

select id from t where num in(1,2,3)

对于连续的数值,能用 beeen 就不要用 in 了:

select id from t where num beeen 1 and 3

5尽量避免在索引过的字符数据中,使用非打头字母搜索。这也使得引擎无法利用索引。

见如下例子:

SELECT FROM T1 WHERE NAME LIKE ‘%L%’

SELECT FROM T1 WHERE SUBSTING(NAME,2,1)=’L’

SELECT FROM T1 WHERE NAME LIKE ‘L%’

即使NAME字段建有索引,前两个查询依然无法利用索引完成加快 *** 作,引擎不得不对全表所有数据逐条 *** 作来完成任务。而第三个查询能够使用索引来加快 *** 作。

6必要时强制查询优化器使用某个索引,如在 where 子句中使用参数,也会导致全表扫描。因为SQL只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推迟到运行时;它必须在编译时进行选择。然而,如果在编译时建立访问计划,变量的值还是未知的,因而无法作为索引选择的输入项。如下面语句将进行全表扫描:

select id from t where num=@num

可以改为强制查询使用索引:

select id from t with(index(索引名)) where num=@num

7应尽量避免在 where 子句中对字段进行表达式 *** 作,这将导致引擎放弃使用索引而进行全表扫描。如:

SELECT FROM T1 WHERE F1/2=100

应改为:

SELECT FROM T1 WHERE F1=1002

SELECT FROM RECORD WHERE SUBSTRING(CARD_NO,1,4)=’5378’

应改为:

SELECT FROM RECORD WHERE CARD_NO LIKE ‘5378%’

SELECT member_number, first_name, last_name FROM members

WHERE DATEDIFF(yy,datofbirth,GETDATE()) > 21

应改为:

SELECT member_number, first_name, last_name FROM members

WHERE dateofbirth < DATEADD(yy,-21,GETDATE())

即:任何对列的 *** 作都将导致表扫描,它包括数据库函数、计算表达式等等,查询时要尽可能将 *** 作移至等号右边。

8应尽量避免在where子句中对字段进行函数 *** 作,这将导致引擎放弃使用索引而进行全表扫描。如:

select id from t where substring(name,1,3)='abc'--name以abc开头的id

select id from t where datediff(day,createdate,'2005-11-30')=0--‘2005-11-30’生成的id

应改为:

select id from t where name like 'abc%'

select id from t where createdate>='2005-11-30' and createdate<'2005-12-1'

9不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。

10在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致。

11很多时候用 exists是一个好的选择:

elect num from a where num in(select num from b)

用下面的语句替换:

select num from a where exists(select 1 from b where num=anum)

SELECT SUM(T1C1)FROM T1 WHERE(

(SELECT COUNT()FROM T2 WHERE T2C2=T1C2>0)

SELECT SUM(T1C1) FROM T1WHERE EXISTS(

SELECT FROM T2 WHERE T2C2=T1C2)

两者产生相同的结果,但是后者的效率显然要高于前者。因为后者不会产生大量锁定的表扫描或是索引扫描。

Java怎么把数据库的数据查询

Statement stmt = null;

ResultSet rs = null;

String query = "select 列名 from 表名 where id=11 and fname='xx' order by 列名 desc limit 1";

stmt = conncreateStatement();

rs = stmtexecuteQuery(query);

if (rsnext()) {

result = rsgetInt("列名");

}

数据库表内数据查询

楼上的 拼写错误,我来修正 ^^

select count() from 表名

如何查询大数据库数据存在

传统数据库处理大数据很困难吧,不建议使用传统数据库来处理大数据。

建议研究下,Hadoop,Hive等,可处理大数据。

如果有预算,可以使用一些商业大数据产品,国内的譬如永洪科技的大数据BI产品,不仅能高性能处理大数据,还可做数据分析。

当然如果是简单的查询,传统数据库如果做好索引,可能可以提高性能。

如何实现不同数据库的数据查询分页

有两种方法

方法1:

select 100 from tbllendlist where fldserialNo not in ( select 300100 fldserialNo from tbllendlist order by fldserialNo ) order by fldserialNo

方法2:

SELECT TOP 100 FROM tbllendlist WHERE (fldserialNo > (SELECT MAX(fldserialNo) FROM (SELECT TOP 300100 fldserialNo FROM tbllendlist ORDER BY fldserialNo) AS T)) ORDER BY fldserialNo

如何提高Oracle数据库数据查询的命中率

影响命中率的因素有四种:字典表活动、临时段活动、回滚段活动、表扫描, 应用DBA可以对这四种因素进行分析,找出数据库命中率低的症结所在。 1)字典表活动 当一个SQL语句第一次到达Oracle内核时数据库对SQL语句进行分析,包含在查询中的数据字典对象被分解,产生SQL执行路径。如果SQL语句指向一个不在SGA中的对象表或视图,Oracle执行SQL语句到数据典中查询有关对象的信息。数据块从数据字典表被读取到SGA的数据缓存中。由于每个数据字典都很小,因此,我们可缓存这些表以提高对这些表的命中率。但是由于数据字典表的数据块在SGA中占据空间,当增加全部的命中率时,它们会降低表数据块的可用空间, 所以若查询所需的时间字典信息已经在SGA缓存中,那么就没有必要递归调用。 2)临时段的活动 当用户执行一个需要排序的查询时,Oracle设法对内存中排序区内的所有行进行排序,排序区的大小由数据库的initora文件的数确定。如果排序区域不够大,数据库就会在排序 *** 作期间开辟临时段。临时段会人为地降低OLTP(online transaction processing)应用命中率,也会降低查询进行排序的性能。如果能在内存中完成全部排序 *** 作,就可以消除向临时段写数据的开销。所以应将SORT_AREA_SIZE设置得足够大,以避免对临时段的需要。这个参数的具体调整方法是:查询相关数据,以确定这个参数的调整。 select from v$sysstat where name='sorts(disk)'or name='sorts(memory); 大部分排序是在内存中进行的,但还有小部分发生在临时段, 需要调整 值,查看initora文件的 SORT_AREA_SIZE值,参数为:SORT_AREA_SIZE=65536;将其调整到SORT_AREA_SIZE=131072、这个值调整后,重启ORACLE数据库即可生效。 3)回滚段的活动 回滚段活动分为回滚活动和回滚段头活动。对回滚段头块的访问会降低应用的命中率, 对OLTP系统命中率的影响最大。为确认是否因为回滚段影响了命中率,可以查看监控输出报表中的“数据块相容性读一重写记录应用” 的统计值,这些统计值是用来确定用户从回滚段中访问数据的发生次数。 4)表扫描 通过大扫描读得的块在数据块缓存中不会保持很长时间, 因此表扫描会降低命中率。为了避免不必要的全表扫描,首先是根据需要建立索引,合理的索引设计要建立人对各种查询的分析和预测上,笔者会在SQL优化中详细谈及;其次是将经常用到的表放在内存中,以降低磁盘读写次数。

如何优化数据库提高数据库的效率

1 SQL优化的原则是:将一次 *** 作需要读取的BLOCK数减到最低,即在最短的时间达到最大的数据吞吐量。

调整不良SQL通常可以从以下几点切入:

检查不良的SQL,考虑其写法是否还有可优化内容

检查子查询 考虑SQL子查询是否可以用简单连接的方式进行重新书写

检查优化索引的使用

考虑数据库的优化器

2 避免出现SELECT FROM table 语句,要明确查出的字段。

3 在一个SQL语句中,如果一个where条件过滤的数据库记录越多,定位越准确,则该where条件越应该前移。

4 查询时尽可能使用索引覆盖。即对SELECT的字段建立复合索引,这样查询时只进行索引扫描,不读取数据块。

5 在判断有无符合条件的记录时建议不要用SELECT COUNT ()和select 1 语句。

6 使用内层限定原则,在拼写SQL语句时,将查询条件分解、分类,并尽量在SQL语句的最里层进行限定,以减少数据的处理量。

7 应绝对避免在order by子句中使用表达式。

8 如果需要从关联表读数据,关联的表一般不要超过7个。

9 小心使用 IN 和 OR,需要注意In集合中的数据量。建议集合中的数据不超过200个。

10 <> 用 < 、 > 代替,>用>=代替,<用<=代替,这样可以有效的利用索引。

11 在查询时尽量减少对多余数据的读取包括多余的列与多余的行。

12 对于复合索引要注意,例如在建立复合索引时列的顺序是F1,F2,F3,则在where或order by子句中这些字段出现的顺序要与建立索引时的字段顺序一致,且必须包含第一列。只能是F1或F1,F2或F1,F2,F3。否则不会用到该索引。

13 多表关联查询时,写法必须遵循以下原则,这样做有利于建立索引,提高查询效率。格式如下select sum(table1je) from table1 table1, table2 table2, table3 table3 where (table1的等值条件(=)) and (table1的非等值条件) and (table2与table1的关联条件) and (table2的等值条件) and (table2的非等值条件) and (table3与table2的关联条件) and (table3的等值条件) and (table3的非等值条件)。

注:关于多表查询时from 后面表的出现顺序对效率的影响还有待研究。

14 子查询问题。对于能用连接方式或者视图方式实现的功能,不要用子查询。例如:select name from customer where customer_id in ( select customer_id from order where money>1000)。应该用如下语句代替:select name from customer inner join order on customercustomer_id=ordercustomer_id where ordermoney>100。

15 在WHERE 子句中,避免对列的四则运算,特别是where 条件的左边,严禁使用运算与函数对列进行处理。比如有些地方 substring 可以用like代替。

16 如果在语句中有not in(in) *** 作,应考虑用not exists(exists)来重写,最好的办法是使用外连接实现。

17 对一个业务过程的处理,应该使事物的开始与结束之间的时间间隔越短越好,原则上做到数据库的读 *** 作在前面完成,数据库写 *** 作在后面完成,避免交叉。

18 请小心不要对过多的列使用列函数和order by,group by等,谨慎使用disti软件开发t。

19 用union all 代替 union,数据库执行union *** 作,首先先分别执行union两端的查询,将其放在临时表中,然后在对其进行排序,过滤重复的记录。

当已知的业务逻辑决定query A和query B中不会有重复记录时,应该用union all代替union,以提高查询效率。

数据更新的效率

1 在一个事物中,对同一个表的多个insert语句应该集中在一起执行。

2 在一个业务过程中,尽量的使insert,update,delete语句在业务结束前执行,以减少死锁的可能性。

数据库物理规划的效率

为了避免I/O的冲突,我们在设计数据库物理规划时应该遵循几条基本的原则(以ORACLE举例):

table和index分离:table和index应该分别放在不同的tablespace中。

Rollback Segment的分离:Rollback Segment应该放在独立的Tablespace中。

System Tablespace的分离:System Tablespace中不允许放置任何用户的object。(mssql中primary filegroup中不允许放置任何用户的object)

Temp Tablesace的分离:建立单独的Temp Tablespace,并为每个user指定default Temp Tablespace

避免碎片:但segment中出现大量的碎片时,会导致读数据时需要访问的block数量的增加。对经常发生DML *** 作的segemeng来说,碎片是不能完全避免的。所以,我们应该将经常做DML *** 作的表和很少发生变化的表分离在不同的Tablespace中。

当我们遵循了以上原则后,仍然发现有I/O冲突存在,我们可以用数据分离的方法来解决。

连接Table的分离:在实际应用中经常做连接查询的Table,可以将其分离在不同的Taclespace中,以减少I/O冲突。

使用分区:对数据量很大的Table和Index使用分区,放在不同的Tablespace中。

在实际的物理存储中,建议使用RAID。日志文件应放在单独的磁盘中。

数据库的查询优化算法

给出你的查询,然后才可以对其进行优化

如何优化SQL Server数据库查询

如果你的查询比较固定,并且查询的条件区别度较高,可以建立相应的索引。

其他的一些规则,比如使用exists代替 in都可以试试

查询速度慢的原因很多,常见如下几种:

1、没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷)

2、I/O吞吐量小,形成了瓶颈效应。

3、没有创建计算列导致查询不优化。

4、内存不足

5、网络速度慢

6、查询出的数据量过大(可以采用多次查询,其他的方法降低数据量)

7、锁或者死锁(这也是查询慢最常见的问题,是程序设计的缺陷)

8、sp_lock,sp_who,活动的用户查看,原因是读写竞争资源。

9、返回了不必要的行和列

10、查询语句不好,没有优化

可以通过如下方法来优化查询 :

1、把数据、日志、索引放到不同的I/O设备上,增加读取速度,以前可以将Tempdb应放在RAID0上,SQL2000不在支持。数据量(尺寸)越大,提高I/O越重要

2、纵向、横向分割表,减少表的尺寸(sp_spaceuse)

3、升级硬件

4、根据查询条件,建立索引,优化索引、优化访问方式,限制结果集的数据量。注意填充因子要适当(最好是使用默认值0)。索引应该尽量小,使用字节数小的列建索引好(参照索引的创建),不要对有限的几个值的字段建单一索引如性别字段

5、提高网速;

6、扩大服务器的内存,Windows 2000和SQL server 2000能支持4-8G的内存。配置虚拟内存:虚拟内存大小应基于计算机上并发运行的服务进行配置。运行 Microsoft SQL Server 2000 时,可考虑将虚拟内存大小设置为计算机中安装的物理内存的 15 倍。如果另外安装了全文检索功能,并打算运行 Microsoft 搜索服务以便执行全文索引和查询,可考虑:将虚拟内存大小配置为至少是计算机中安装的物理内存的 3 倍。将 SQL Server max server memory 服务器配置选项配置为物理内存的 15 倍(虚拟内存大小设置的一半)。

7、增加服务器 CPU个数; 但是必须明白并行处理串行处理更需要资源例如内存。使用并行还是串行程是MsSQL自动评估选择的。单个任务分解成多个任务,就可以在处理器上运行。例如耽搁查询的排序、连接、扫描和GROUP BY字句同时执行,SQL SERVER根据系统的负载情况决定最优的并行等级,复杂的需要消耗大量的CPU的查询最适合并行处理。但是更新 *** 作Update,Insert, Delete还不能并行处理。

8、如果是使用like进行查询的话,简单的使用index是不行的,但是全文索引,耗空间。 like 'a%' 使用索引 like '%a' 不使用索引用 like '%a%' 查询时,查询耗时和字段值总长度成正比,所以不能用CHAR类型,而是VARCHAR。对于字段的值很长的建全文索引。

9、DB Server 和APPLication Server 分离;OLTP和OLAP分离

10、分布式分区视图可用于实现数据库服务器联合体。联合体是一组分开管理的服务器,但它们相互协作分担系统的处理负荷。这种通过分区数据形成数据库服务器联合体的机制能够扩大一组服务器,以支持大型的多层 Web 站点的处理需要。有关更多信息,参见设计联合数据库服务器。(参照SQL帮助文件'分区视图')

a、在实现分区视图之前,必须先水平分区表

b、在创建成员表后,在每个成员服务器上定义一个分布式分区视图,并且每个视图具有相同的名称。这样,引用分布式分区视图名的查询可以在任何一个成员服务器上运行。系统 *** 作如同每个成员服务器上都有一个原始表的复本一样,但其实每个服务器上只有一个成员表和一个分布式分区视图。数据的位置对应用程序是透明的。

11、重建索引 DBCC REINDEX ,DBCC INDEXDEFRAG,收缩数据和日志 DBCC SHRINKDB,DBCC SHRINKFILE 设置自动收缩日志对于大的数据库不要设置数据库自动增长,它会降低服务器的性能。在T-sql的写法上有很大的讲究,下面列出常见的要点:首先,DBMS处理查询计划的过程是这样的:

1、 查询语句的词法、语法检查

2、 将语句提交给DBMS的查询优化器

3、 优化器做代数优化和存取路径的优化

4、 由预编译模块生成查询规划

5、 然后在合适的时间提交给系统处理执行

6、 最后将执行结果返回给用户其次,看一下SQL SERVER的数据存放的结构:一个页面的大小为8K(8060)字节,8个页面为一个盘区,按照B树存放。

12、Commit和rollback的区别 Rollback:回滚所有的事物。 Commit:提交当前的事物 没有必要在动态SQL里写事物,如果要写请写在外面如: begin tran exec(@s) mit trans 或者将动态SQL 写成函数或者存储过程。

13、在查询Select语句中用Where字句限制返回的行数,避免表扫描,如果返回不必要的数据,浪费了服务器的I/O资源,加重了网络的负担降低性能。如果表很大,在表扫描的期间将表锁住,禁止其他的联接访问表,后果严重。

14、SQL的注释申明对执行没有任何影响

15、尽可能不使用光标,它占用大量的资源。如果需要row-by-row地执行,尽量采用非光标技术,如:在客户端循环,用临时表,Table变量,用子查询,用Case语句等等。游标可以按照它所支持的提取选项进行分类: 只进 必须按照从第一行到最后一行的顺序提取行。FETCH NEXT 是唯一允许的提取 *** 作,也是默认方式。可滚动性可以在游标中任何地方随机提取任意行。游标的技术在SQL2000下变得功能很强大,他的目的是支持循环。有四个并发选项 READ_ONLY:不允许通过游标定位更新(Update),且在组成结果集的行中没有锁。 OPTIMISTIC WITH valueS:乐观并发控制是事务控制理论的一个标准部分。乐观并发控制用于这样的情形,即在打开游标及更新行的间隔中,只有很小的机会让第二个用户更新某一行。当某个游标以此选项打开时,没有锁控制其中的行,这将有助于最大化其处理能力。如果用户试图修改某一行,则此行的当前值会与最后一次提取此行时获取的值进行比较。如果任何值发生改变,则服务器就会知道其他人已更新了此行,并会返回一个错误。如果值是一样的,服务器就执行修改。选择这个并发选项OPTIMISTIC WITH ROW VERSIONING:此乐观并发控制选项基于行版本控制。使用行版本控制,其中的表必须具有某种版本标识符,服务器可用它来确定该行在读入游标后是否有所更改。在 SQL Server 中,这个性能由 timestamp 数据类型提供,它是一个二进制数字,表示数据库中更改的相对顺序。每个数据库都有一个全局当前时间戳值:@@DBTS。每次以任何方式更改带有 timestamp 列的行时,SQL Server 先在时间戳列中存储当前的 @@DBTS 值,然后增加 @@DBTS 的值。如果某 个表具有 timestamp 列,则时间戳会被记到行级。服务器就可以比较某行的当前时间戳值和上次提取时所存储的时间戳值,从而确定该行是否已更新。服务器不必比较所有列的值,只需比较 timestamp 列即可。如果应用程序对没有 timestamp 列的表要求基于行版本控制的乐观并发,则游标默认为基于数值的乐观并发控制。 SCROLL LOCKS 这个选项实现悲观并发控制。在悲观并发控制中,在把数据库的行读入游标结果集时,应用程序将试图锁定数据库行。在使用服务器游标时,将行读入游标时会在其上放置一个更新锁。如果在事务内打开游标,则该事务更新锁将一直保持到事务被提交或回滚;当提取下一行时,将除去游标锁。如果在事务外打开游标,则提取下一行时,锁就被丢弃。因此,每当用户需要完全的悲观并发控制时,游标都应在事务内打开。更新锁将阻止任何其它任务获取更新锁或排它锁,从而阻止其它任务更新该行。然而,更新锁并不阻止共享锁,所以它不会阻止其它任务读取行,除非第二个任务也在要求带更新锁的读取。滚动锁根据在游标定义的 Select 语句中指定的锁提示,这些游标并发选项可以生成滚动锁。滚动锁在提取时在每行上获取,并保持到下次提取或者游标关闭,以先发生者为准。下次提取时,服务器为新提取中的行获取滚动锁,并释放上次提取中行的滚动锁。滚动锁独立于事务锁,并可以保持到一个提交或回滚 *** 作之后。如果提交时关闭游标的选项为关,则 COMMIT 语句并不关闭任何打开的游标,而且滚动锁被保留到提交之后,以维护对所提取数据的隔离。所获取滚动锁的类型取决于游标并发选项和游标 Select 语句中的锁提示。锁提示 只读 乐观数值 乐观行版本控制 锁定无提示 未锁定 未锁定 未锁定 更新 NOLOCK 未锁定 未锁定未锁定 未锁定 HOLDLOCK 共享 共享 共享 更新 UPDLOCK 错误 更新 更新 更新 TABLOCKX 错误 未锁定 未锁定更新其它 未锁定 未锁定 未锁定 更新 指定 NOLOCK 提示将使指定了该提示的表在游标内是只读的。

16、用Profiler来跟踪查询,得到查询所需的时间,找出SQL的问题所在; 用索引优化器优化索引

17、注意UNion和UNion all 的区别。UNION all好

18、注意使用DISTINCT,在没有必要时不要用,它同UNION一样会使查询变慢。重复的记录在查询里是没有问题的

19、查询时不要返回不需要的行、列

20、用sp_configure 'query governor cost limit'或者SET QUERY_GOVERNOR_COST_LIMIT来限制查询消耗的资源。当评估查询消耗的资源超出限制时,服务器自动取消查询,在查询之前就扼杀掉。 SET LOCKTIME设置锁的时间

21、用select 100 / 10 Percent 来限制用户返回的行数或者SET ROWCOUNT来限制 *** 作的行

22、在SQL2000以前,一般不要用如下的字句: "IS NULL", "<>", "!=", "!>", "!<", "NOT", "NOT EXISTS", "NOT IN", "NOT LIKE", and "LIKE '%500'",因为他们不走索引全是表扫描。也不要在Where字句中的列名加函数,如Convert,substring等,如果必须用函数的时候,创建计算列再创建索引来替代还可以变通写法:Where SUBSTRING(firstname,1,1) = 'm'改为Where firstname like 'm%'(索引扫描),一定要将函数和列名分开。并且索引不能建得太多和太大。NOT IN会多次扫描表,使用EXISTS、NOT EXISTS ,IN , LEFT OUTER JOIN 来替代,特别是左连接,而Exists比IN更快,最慢的是NOT *** 作如果列的值含有空,以前它的索引不起作用,现在2000的优化器能够处理了。相同的是IS NULL,"NOT", "NOT EXISTS", "NOT IN"能优化她,而"<>"等还是不能优化,用不到索引。

23、使用Query Analyzer,查看SQL语句的查询计划和评估分析是否是优化的SQL。一般的20%的代码占据了80%的资源,我们优化的重点是这些慢的地方。

24、如果使用了IN或者OR等时发现查询没有走索引,使用显示申明指定索引: Select FROM PersonMember (INDEX = IX_Title) Where processid IN ('男','女')

25、将需要查询的结果预先计算好放在表中,查询的时候再Select。这在SQL70以前是最重要的手段。例如医院的住院费计算。

26、MIN() 和 MAX()能使用到合适的索引。

27、数据库有一个原则是代码离数据越近越好,所以优先选择Default,依次为Rules,Triggers, Constraint(约束如外健主健CheckUNIQUE……,数据类型的最大长度等等都是约束),Procedure这样不仅维护工作小,编写程序质量高,并且执行的速度快。

28、如果要插入大的二进制值到Image列,使用存储过程,千万不要用内嵌Insert来插入(不知JAVA是否)。因为这样应用程序首先将二进制值转换成字符串(尺寸是它的两倍),服务器受到字符后又将他转换成二进制值存储过程就没有这些动作: 方法:Create procedure p_insert as insert into table(Fimage) values (@image), 在前台调用这个存储过程传入二进制参数,这样处理速度明显改善

PostgresSQL提供了许多数据库配置参数,本章将介绍每个参数的作用和如何配置每一个参数。

101 如何设置数据库参数

所有的参数的名称都是不区分大小写的。每个参数的取值是布尔型、整型、浮点型和字符串型这四种类型中的一个,分别用boolean

、integer、 floating point和string表示。布尔型的值可以写成ON、OFF、 TRUE、 FALSE、 YES、 NO、 1和 0,而且不区分大小

写。

有些参数用来配置内存大小和时间值。内存大小的单位可以是KB、MB和GB。时间的单位可以是毫秒、秒、分钟、小时和天。用ms表示

毫秒,用s表示秒,用 min表示分钟,用h表示小时,用d表示天。表示内存大小和时间值的参数参数都有一个默认的单位,如果用户

在设置参数的值时没有指定单位,则以参数默认的 单位为准。例如,参数shared_buffers表示数据缓冲区的大小,它的默认单位是

数据块的个数,如果把它的值设成8,因为每个数据块的大小是 8KB,则数据缓冲区的大小是88=64KB,如果将它的值设成128MB,

则数据缓冲区的大小是128MB。参数vacuum_cost_delay 的默认单位是毫秒,如果把它的值设成10,则它的值是10毫秒,如果把它的

值设成100s,则它的值是100秒。

所有的参数都放在文件 postgresqlconf中,下面是一个文件实例:

#这是注释

log_connections = yes

log_destination = 'syslog'

search_path = '"$user", public'

每一行只能指定一个参数,空格和空白行都会被忽略。“ #”表示注释,注释信息不用单独占一行,可以出现在配置文件的任何地方

。如果参数的值不是简单的标识符和数字,应该用单引号引起来。如果参数的值中有单引号,应该写两个单引号,或者在单引号前面

加一个反斜杠。

一个配置文件也可以包含其它配置文件,使用include指令能够达到这个目的,例如,假设postgresqlconf文件中有下面一行:

include ‘myconfg’

文件myconfig中的配置信息也会被数据库读入。include指令指定的配置文件也可以用include指令再包含其它配置文件。如果

include指令中指定的文件名不是绝对路径,数据库会在postgresqlconf文件所在的目录下查找这个文件。

用户也可以在数据库启动以后修改postgresqlconf配置文件,使用命令pg_ctl reload来通知数据库重新读取配置文件。注意,有些

参数在数据库启动以后,不能被修改,只有重新启动数据库以后,新的参数值才能生效。另外一些参数可 以在数据库运行过程中被

修改而且新的值可以立即生效。所以数据库在运行过程中重新读取参数配置文件以后,不是所有的参数都会被赋给新的值。

用户可以在自己建立的会话中执行命令SET修改某些配置参数的值(注意不是全部参数),例如:

SET ENABLE_SEQSCAN TO OFF;

另外,有些参数只有数据库超级用户才能使用SET命令修改它们。用户可以在psql中执行命令show来查看所有的数据库参数的当前值

。例如:

(1)show all; --查看所有数据库参数的值

(2)show search_path; --查看参数search_path的值

102 连接与认证

1021 连接设置

listen_addresses (string)

这个参数只有在启动数据库时,才能被设置。它指定数据库用来监听客户端连接的TCP/IP地址。默认是值是 ,表示数据库在启动以

后将在运行数据的机器上的所有的IP地址上监听用户请求(如果机器只有一个网卡,只有一个IP地址,有多个网卡的机器有多个 IP

地址)。可以写成机器的名字,也可以写成IP地址,不同的值用逗号分开,例如,’server01’, ’1408717149, 1408717121

’。如果被设成localhost,表示数据库只能接受本地的客户端连接请求,不能接受远程的客户端连接请求。

port (integer)

这个参数只有在启动数据库时,才能被设置。它指定数据库监听户端连接的TCP端口。默认值是5432。

max_connections (integer)

这个参数只有在启动数据库时,才能被设置。它决定数据库可以同时建立的最大的客户端连接的数目。默认值是100。

superuser_reserved_connections (integer)

这个参数只有在启动数据库时,才能被设置。它表示预留给超级用户的数据库连接数目。它的值必须小于max_connections。 普通用

户可以在数据库中建立的最大的并发连接的数目是max_connections- superuser_reserved_connections, 默认值是3。

unix_socket_group (string)

这个参数只有在启动数据库时,才能被设置。设置Unix-domain socket所在的 *** 作系统用户组。默认值是空串,用启动数据库的 *** 作

系统用户所在的组作为Unix-domain socket的用户组。

unix_socket_permissions (integer)

这个参数只有在启动数据库时,才能被设置。它设置Unix-domain socket的访问权限,格式与 *** 作系统的文件访问权限是一样的。默

认值是0770,表示任何 *** 作系统用户都能访问Unix-domain socket。可以设为0770(所有Unix-domain socket文件的所有者所在的组

包含的用户都能访问)和0700(只有Unix-domain socket文件的所有者才能访问)。对于Unix-domain socket,只有写权限才有意义,

读和执行权限是没有意义的。

tcp_keepalives_idle (integer)

这个参数可以在任何时候被设置。默认值是0,意思是使用 *** 作系统的默认值。它设置TCP套接字的TCP_KEEPIDLE属性。这个参数对于

通过Unix-domain socket建立的数据库连接没有任何影响。

tcp_keepalives_interval (integer)

这个参数可以在任何时候被设置。默认值是0,意思是使用 *** 作系统的默认值。它设置TCP套接字的TCP_KEEPINTVL属性。这个参数对

于通过Unix-domain socket建立的数据库连接没有任何影响。

tcp_keepalives_count (integer)

这个参数可以在任何时候被设置。默认值是0,意思是使用 *** 作系统的默认值。它设置TCP套接字的TCP_KEEPCNT属性。这个参数对于

通过Unix-domain socket建立的数据库连接没有任何影响。

1022 安全与认证

authentication_timeout (integer)

这个参数只能在postgresqlconf文件中被设置,它指定一个时间长度,在这个时间长度内,必须完成客户端认证 *** 作,否则客户端

连接请求将被拒绝。它可以阻止某些客户端进行认证时长时间占用数据库连接。单位是秒,默认值是60。

ssl (boolean)

这个参数只有在启动数据库时,才能被设置。决定数据库是否接受SSL连接。默认值是off。

ssl_ciphers (string)

指定可以使用的SSL加密算法。查看 *** 作系统关于openssl的用户手册可以得到完整的加密算法列表(执行命令openssl ciphers –v

也可以得到)。

103 资源消耗

1031 内存

shared_buffers (integer)

这个参数只有在启动数据库时,才能被设置。它表示数据缓冲区中的数据块的个数,每个数据块的大小是8KB。数据缓冲区位于数据

库的共享内存中,它越大越好,不能小于128KB。默认值是1024。

temp_buffers (integer)

这个参数可以在任何时候被设置。默认值是8MB。它决定存放临时表的数据缓冲区中的数据块的个数,每个数据块的大小是8KB。临时

表缓冲区存放在每个数据库进程的私有内存中,而不是存放在数据库的共享内存中。默认值是1024。

max_prepared_transactions (integer)

这个参数只有在启动数据库时,才能被设置。它决定能够同时处于prepared状态的事务的最大数目(参考PREPARE TRANSACTION命令

)。如果它的值被设为0。则将数据库将关闭prepared事务的特性。它的值通常应该和max_connections的值 一样大。默认值是5。

work_mem (integer)

这个参数可以在任何时候被设置。它决定数据库的排序 *** 作和哈希表使用的内存缓冲区的大小。如何work_mem指定的内存被耗尽,数

据库将使用磁盘文件进 行完成 *** 作,速度会慢很多。ORDER BY、DISTINCT和merge连接会使用排序 *** 作。哈希表在Hash连接、hash聚

集函数和用哈希表来处理IN谓词中的子查询中被使用。单位是 KB,默认值是1024。

maintenance_work_mem (integer)

这个参数可以在任何时候被设置。它决定数据库的维护 *** 作使用的内存空间的大小。数据库的维护 *** 作包括VACUUM、CREATE INDEX和

ALTER TABLE ADD FOREIGN KEY等 *** 作。 maintenance_work_mem的值如果比较大,通常可以缩短VACUUM数据库和从dump文件中恢复数

据库需要的时间。 maintenance_work_mem存放在每个数据库进程的私有内存中,而不是存放在数据库的共享内存中。单位是KB,默

认值是16384。

max_stack_depth (integer)

这个参数可以在任何时候被设置,但只有数据库超级用户才能修改它。它决定一个数据库进程在运行时的STACK所占的空间的最大值

。数据库进程在运行时,会 自动检查自己的STACK大小是否超过max_stack_depth,如果超过,会自动终止当前事务。这个值应该比

*** 作系统设置的进程STACK的大小 的上限小1MB。使用 *** 作系统命令“ulimit –s“可以得到 *** 作系统设置的进程STACK的最大值。单

位是KB,默认值是100。

1032 Free Space Map

数据库的所有可用空间信息都存放在一个叫free space map (FSM)的结构中,它记载数据文件中每个数据块的可用空间的大小。FSM

中没有记录的数据块,即使有可用空间,也不会系统使用。系统如果需要新的物理存 储空间,会首先在FSM中查找,如果FSM中没有

一个数据页有足够的可用空间,系统就会自动扩展数据文件。所以,FSM如果太小,会导致系统频繁地扩展数 据文件,浪费物理存储

空间。命令VACUUM VERBOSE在执行结束以后,会提示当前的FSM设置是否满足需要,如果FSM的参数值太小,它会提示增大参数。

FSM存放在数据库的共享内存中,由于物理内存的限制,FSM不可能跟踪数据库的所有的数据文件的所有数据块的可用空间信息,只能

跟踪一部分数据块的可用空间信息。

max_fsm_relations (integer)

这个参数只有在启动数据库时,才能被设置。默认值是1000。它决定FSM跟踪的表和索引的个数的上限。每个表和索引在FSM中占7个

字节的存储空间。

max_fsm_pages (integer)

这个参数只有在启动数据库时,才能被设置。它决定FSM中跟踪的数据块的个数的上限。initdb在创建数据库集群时会根据物理内存

的大小决定它的值。每 个数据块在fsm中占6个字节的存储空间。它的大小不能小于16 max_fsm_relations。默认值是20000。

1033 内核资源

max_files_per_process (integer)

这个参数只有在启动数据库时,才能被设置。他设定每个数据库进程能够打开的文件的数目。默认值是1000。

shared_preload_libraries (string)

这个参数只有在启动数据库时,才能被设置。它设置数据库在启动时要加载的 *** 作系统共享库文件。如果有多个库文件,名字用逗号

分开。如果数据库在启动时未找到shared_preload_libraries指定的某个库文件,数据库将无法启动。默认值为空串。

1034 垃圾收集

执行VACUUM 和ANALYZE命令时,因为它们会消耗大量的CPU与IO资源,而且执行一次要花很长时间,这样会干扰系统执行应用程序发

出的SQL命令。为了解决这个 问题,VACUUM 和ANALYZE命令执行一段时间后,系统会暂时终止它们的运行,过一段时间后再继续执行

这两个命令。这个特性在默认的情况下是关闭的。将参数 vacuum_cost_delay设为一个非零的正整数就可以打开这个特性。

用户通常只需要设置参数vacuum_cost_delay和vacuum_cost_limit,其它的参数使用默认值即可。VACUUM 和ANALYZE命令在执行过程

中,系统会计算它们执行消耗的资源,资源的数量用一个正整数表示,如果资源的数量超过 vacuum_cost_limit,则执行命令的进程

会进入睡眠状态,睡眠的时间长度是是vacuum_cost_delay。 vacuum_cost_limit的值越大,VACUUM 和ANALYZE命令在执行的过程中

,睡眠的次数就越少,反之,vacuum_cost_limit的值越小,VACUUM 和ANALYZE命令在执行的过程中,睡眠的次数就越多。

vacuum_cost_delay (integer)

这个参数可以在任何时候被设置。默认值是0。它决定执行VACUUM 和ANALYZE命令的进程的睡眠时间。单位是微秒。它的值最好是10

的整数,如果不是10的整数,系统会自动将它设为比该值大的并且最接近该值的是10 的倍数的整数。如果值是0,VACUUM 和ANALYZE

命令在执行过程中不会主动进入睡眠状态,会一直执行下去直到结束。

vacuum_cost_page_hit (integer)

这个参数可以在任何时候被设置。默认值是1。

vacuum_cost_page_miss (integer)

这个参数可以在任何时候被设置。默认值是10。

vacuum_cost_page_dirty (integer)

这个参数可以在任何时候被设置。默认值是20。

vacuum_cost_limit (integer)

这个参数可以在任何时候被设置。默认值是200。

1035 后台写数据库进程

后台写数据库进程负责将数据缓冲区中的被修改的数据块(又叫脏数据块)写回到数据库物理文件中。

bgwriter_delay (integer)

这个参数只能在文件postgresqlconf中设置。它决定后台写数据库进程的睡眠时间。后台写数据库进程每次完成写数据到物理文件

中的任务以后, 就会睡眠bgwriter_delay指定的时间。 bgwriter_delay的值应该是10的倍数,如果用户设定的值不是10的倍数,数

据库会自动将参数的值设为比用户指定的值大的最接近用户指定的值 的同时是10的倍数的值。单位是毫秒,默认值是200。

bgwriter_lru_maxpages (integer)

这个参数只能在文件postgresqlconf中设置。默认值是100。后台写数据库进程每次写脏数据块时,写到外部文件中的脏数据块的个

数不能超过 bgwriter_lru_maxpages指定的值。例如,如果它的值是500,则后台写数据库进程每次写到物理文件的数据页的个数不

能超过500,若 超过,进程将进入睡眠状态,等下次醒来再执行写物理文件的任务。如果它的值被设为0, 后台写数据库进程将不会

写任何物理文件(但还会执行检查点 *** 作)。

bgwriter_lru_multiplier (floating point)

这个参数只能在文件postgresqlconf中设置。默认值是20。它决定后台写数据库进程每次写物理文件时,写到外部文件中的脏数据

块的个数 (不能超过bgwriter_lru_maxpages指定的值)。一般使用默认值即可,不需要修改这个参数。这个参数的值越大,后台写

数据库进程每次写 的脏数据块的个数就越多。

104 事务日志

full_page_writes (boolean)

这个参数只能在postgresqlconf文件中被设置。默认值是on。打开这个参数,可以提高数据库的可靠性,减少数据丢失的概率,但

是会产生过多的事务日志,降低数据库的性能。

wal_buffers (integer)

这个参数只有在启动数据库时,才能被设置。默认值是8。它指定事务日志缓冲区中包含的数据块的个数,每个数据块的大小是8KB,

所以默认的事务日志缓冲区的大小是88=64KB。事务日志缓冲区位于数据库的共享内存中。

wal_writer_delay (integer)

这个参数只能在postgresqlconf文件中被设置。它决定写事务日志进程的睡眠时间。WAL进程每次在完成写事务日志的任务后,就会

睡眠 wal_writer_delay指定的时间,然后醒来,继续将新产生的事务日志从缓冲区写到WAL文件中。单位是毫秒(millisecond),

默认 值是200。

commit_delay (integer)

这个参数可以在任何时候被设置。它设定事务在发出提交命令以后的睡眠时间,只有在睡眠了commit_delay指定的时间以后,事务产

生的事务日志才会 被写到事务日志文件中,事务才能真正地提交。增大这个参数会增加用户的等待时间,但是可以让多个事务被同

时提交,提高系统的性能。如果数据库中的负载比较 高,而且大部分事务都是更新类型的事务,可以考虑增大这个参数的值。下面

的参数commit_siblings会影响commit_delay是否生效。 默认值是0,单位是微秒(microsecond)。

commit_siblings (integer)

这个参数可以在任何时候被设置。这个参数的值决定参数commit_delay是否生效。假设commit_siblings的值是5,如果一个事务发出

一个提交请求,此时,如果数据库中正在执行的事务的个数大于或等于5,那么该事务将睡眠commit_delay指定的时间。如果数据库

中正在执行的事务 的个数小于5,这个事务将直接提交。默认值是5。

105 检查点

checkpoint_segments (integer)

这个参数只能在postgresqlconf文件中被设置。默认值是3。它影响系统何时启动一个检查点 *** 作。如果上次检查点 *** 作结束以后,

系统产生的事 务日志文件的个数超过checkpoint_segments的值,系统就会自动启动一个检查点 *** 作。增大这个参数会增加数据库崩

溃以后恢复 *** 作需要的时 间。

checkpoint_timeout (integer)

这个参数只能在postgresqlconf文件中被设置。单位是秒,默认值是300。它影响系统何时启动一个检查点 *** 作。如果现在的时间减

去上次检查 点 *** 作结束的时间超过了checkpoint_timeout的值,系统就会自动启动一个检查点 *** 作。增大这个参数会增加数据库崩

溃以后恢复 *** 作需要的时 间。

checkpoint_completion_target (floating point)

这个参数控制检查点 *** 作的执行时间。合法的取值在0到1之间,默认值是05。不要轻易地改变这个参数的值,使用默认值即可。 这

个参数只能在postgresqlconf文件中被设置。

106 归档模式

archive_mode (boolean)

这个参数只有在启动数据库时,才能被设置。默认值是off。它决定数据库是否打开归档模式。

archive_dir (string)

这个参数只有在启动数据库时,才能被设置。默认值是空串。它设定存放归档事务日志文件的目录。

archive_timeout (integer)

这个参数只能在postgresqlconf文件中被设置。默认值是0。单位是秒。如果archive_timeout的值不是0,而且当前时间减去数 据

库上次进行事务日志文件切换的时间大于archive_timeout的值,数据库将进行一次事务日志文件切换。一般情况下,数据库只有在

一个事务日志 文件写满以后,才会切换到下一个事务日志文件,设定这个参数可以让数据库在一个事务日志文件尚未写满的情况下

切换到下一个事务日志文件。

107 优化器参数

1071 存取方法参数

下列参数控制查询优化器是否使用特定的存取方法。除非对优化器特别了解,一般情况下,使用它们默认值即可。

enable_bitmapscan (boolean)

打开或者关闭bitmap-scan 。默认值是 on。

enable_hashagg (boolean)

打开或者关闭hashed aggregation。默认值是 on。

enable_hashjoin (boolean)

打开或者关闭hash-join。默认值是 on。

enable_indexscan (boolean)

打开或者关闭index-scan。默认值是 on。

enable_mergejoin (boolean)

打开或者关闭merge-join。默认值是 on。

enable_nestloop (boolean)

打开或者关闭nested-loop join。默认值是 on。不可能完全不使用nested-loop join,关闭这个参数会让系统在有其它存取方法可

用的情况下,不使用nested-loop join。

enable_seqscan (boolean)

打开或者关闭sequential scan。默认值是 on。不可能完全不使用sequential scan,关闭这个参数会让系统在有其它存取方法可用

的情况下,不使用sequential scan。

假定在程序效率和关键过程相当且不计入缓存等措施的条件下,读写任何类型的数据都没有直接 *** 作文件来的快,不论MSYQL过程如何,最后都要到磁盘上去读这个“文件”(记录存储区等效),所以当然这一切的前提是只读 内容,无关任何排序或查找 *** 作。

动态网站一般都是用数据库来存储信息,如果信息的及时性要求不高 可以加入缓存来减少频繁读写数据库。

两种方式一般都支持,但是绕过 *** 作系统直接 *** 作磁盘的性能较高,而且安全性也较高,数据库系中的磁盘性能一直都是瓶颈,大型数据库一般基于unix

系统,当然win下也有,不常用应为win的不可靠性,unix下,用的是裸设备raw设备,就是没有加工过的设备(unix下的磁盘分区属于特殊设备,

以文件形式统一管理),由dbms直接管理,不通过 *** 作系统,效率很高,可靠性也高,因为磁盘,cache和内存都是自己管理的,大型数据库系统

db2,oracal,informix(不太流行了),mssql算不上大型数据库系统。

1、直接读文件相比数据库查询效率更胜一筹,而且文中还没算上连接和断开的时间。

2、一次读取的内容越大,直接读文件的优势会越明

显(读文件时间都是小幅增长,这跟文件存储的连续性和簇大小等有关系),这个结果恰恰跟书生预料的相反,说明MYSQL对更大文件读取可能又附加了某些 ***

作(两次时间增长了近30%),如果只是单纯的赋值转换应该是差异偏小才对。

3、写文件和INSERT几乎不用测试就可以推测出,数据库效率只会更差。

4、很小的配置文件如果不需要使用到数据库特性,更加适合放到独立文件里存取,无需单独创建数据表或记录,很大的文件比如、音乐等采用文件存储更为方便,只把路径或缩略图等索引信息放到数据库里更合理一些。

5、PHP上如果只是读文件,file_get_contents比fopen、fclose更有效率,不包括判断存在这个函数时间会少3秒左右。

6、fetch_row和fetch_object应该是从fetch_array转换而来的,书生没看过PHP的源码,单从执行上就可以说明fetch_array效率更高,这跟网上的说法似乎相反。

磁盘读写与数据库的关系:

一 磁盘物理结构

(1) 盘片:硬盘的盘体由多个盘片叠在一起构成。

在硬盘出厂时,由硬盘生产商完成了低级格式化(物理格式化),作用是将空白的盘片(Platter)划分为一个个同圆心、不同半径的磁道

(Track),还将磁道划分为若干个扇区(Sector),每个扇区可存储128×2的N次方(N=0123)字节信息,默认每个扇区的大小为

512字节。通常使用者无需再进行低级格式化 *** 作。

(2) 磁头:每张盘片的正反两面各有一个磁头。

(3) 主轴:所有磁片都由主轴电机带动旋转。

(4) 控制集成电路板:复杂!上面还有ROM(内有软件系统)、Cache等。

二 磁盘如何完成单次IO *** 作

(1) 寻道

当控制器对磁盘发出一个IO *** 作命令的时候,磁盘的驱动臂(Actuator

Arm)带动磁头(Head)离开着陆区(Landing

Zone,位于内圈没有数据的区域),移动到要 *** 作的初始数据块所在的磁道(Track)的正上方,这个过程被称为寻道(Seeking),对应消耗的时

间被称为寻道时间(Seek Time);

(2) 旋转延迟

找到对应磁道还不能马上读取数据,这时候磁头要等到磁盘盘片(Platter)旋转到初始数据块所在的扇区(Sector)落在读写磁头正下方之后才能开始读取数据,在这个等待盘片旋转到可 *** 作扇区的过程中消耗的时间称为旋转延时(Rotational Delay);

(3) 数据传送

接下来就随着盘片的旋转,磁头不断的读/写相应的数据块,直到完成这次IO所需要 *** 作的全部数据,这个过程称为数据传送(Data Transfer),对应的时间称为传送时间(Transfer Time)。完成这三个步骤之后单次IO *** 作也就完成了。

根据磁盘单次IO *** 作的过程,可以发现:

单次IO时间 = 寻道时间 + 旋转延迟 + 传送时间

进而推算IOPS(IO per second)的公式为:

IOPS = 1000ms/单次IO时间

三 磁盘IOPS计算

不同磁盘,它的寻道时间,旋转延迟,数据传送所需的时间各是多少?

1 寻道时间

考虑到被读写的数据可能在磁盘的任意一个磁道,既有可能在磁盘的最内圈(寻道时间最短),也可能在磁盘的最外圈(寻道时间最长),所以在计算中我们只考虑平均寻道时间。

在购买磁盘时,该参数都有标明,目前的SATA/SAS磁盘,按转速不同,寻道时间不同,不过通常都在10ms以下:

3 传送时间2 旋转延时

和寻道一样,当磁头定位到磁道之后有可能正好在要读写扇区之上,这时候是不需要额外的延时就可以立刻读写到数据,但是最坏的情况确实要磁盘旋转整整

一圈之后磁头才能读取到数据,所以这里也考虑的是平均旋转延时,对于15000rpm的磁盘就是(60s/15000)(1/2) = 2ms。

(1) 磁盘传输速率

磁盘传输速率分两种:内部传输速率(Internal Transfer Rate),外部传输速率(External Transfer Rate)。

内部传输速率(Internal Transfer Rate),是指磁头与硬盘缓存之间的数据传输速率,简单的说就是硬盘磁头将数据从盘片上读取出来,然后存储在缓存内的速度。

理想的内部传输速率不存在寻道,旋转延时,就一直在同一个磁道上读数据并传到缓存,显然这是不可能的,因为单个磁道的存储空间是有限的;

实际的内部传输速率包含了寻道和旋转延时,目前家用磁盘,稳定的内部传输速率一般在30MB/s到45MB/s之间(服务器磁盘,应该会更高)。

外部传输速率(External Transfer Rate),是指硬盘缓存和系统总线之间的数据传输速率,也就是计算机通过硬盘接口从缓存中将数据读出交给相应的硬盘控制器的速率。

硬盘厂商在硬盘参数中,通常也会给出一个最大传输速率,比如现在SATA30的6Gbit/s,换算一下就是61024/8,768MB/s,通常指的是硬盘接口对外的最大传输速率,当然实际使用中是达不到这个值的。

这里计算IOPS,保守选择实际内部传输速率,以40M/s为例。

(2) 单次IO *** 作的大小

有了传送速率,还要知道单次IO *** 作的大小(IO Chunk Size),才可以算出单次IO的传送时间。那么磁盘单次IO的大小是多少?答案是:不确定。

*** 作系统为了提高 IO的性能而引入了文件系统缓存(File System Cache),系统会根据请求数据的情况将多个来自IO的请求先放在缓存里面,然后再一次性的提交给磁盘,也就是说对于数据库发出的多个8K数据块的读 *** 作有可能放在一个磁盘读IO里就处理了。

还有,有些存储系统也是提供了缓存(Cache),接收到 *** 作系统的IO请求之后也是会将多个 *** 作系统的 IO请求合并成一个来处理。

不管是 *** 作系统层面的缓存还是磁盘控制器层面的缓存,目的都只有一个,提高数据读写的效率。因此每次单独的IO *** 作大小都是不一样的,它主要取决于系统对于数据读写效率的判断。这里以SQL Server数据库的数据页大小为例:8K。

(3) 传送时间

传送时间 = IO Chunk Size/Internal Transfer Rate = 8k/40M/s = 02ms

可以发现:

(31) 如果IO Chunk Size大的话,传送时间会变大,从而导致IOPS变小;

(32) 机械磁盘的主要读写成本,都花在了寻址时间上,即:寻道时间 + 旋转延迟,也就是磁盘臂的摆动,和磁盘的旋转延迟。

(33) 如果粗略的计算IOPS,可以忽略传送时间,1000ms/(寻道时间 + 旋转延迟)即可。

4 IOPS计算示例

以15000rpm为例:

(1) 单次IO时间

单次IO时间 = 寻道时间 + 旋转延迟 + 传送时间 = 3ms + 2ms + 02 ms = 52 ms

(2) IOPS

IOPS = 1000ms/单次IO时间 = 1000ms/52ms = 192 (次)

这里计算的是单块磁盘的随机访问IOPS。

考虑一种极端的情况,如果磁盘全部为顺序访问,那么就可以忽略:寻道时间 + 旋转延迟 的时长,IOPS的计算公式就变为:IOPS = 1000ms/传送时间

IOPS = 1000ms/传送时间= 1000ms/02ms = 5000 (次)

显然这种极端的情况太过理想,毕竟每个磁道的空间是有限的,寻道时间 + 旋转延迟 时长确实可以减少,不过是无法完全避免的。

四 数据库中的磁盘读写

1 随机访问和连续访问

(1) 随机访问(Random Access)

指的是本次IO所给出的扇区地址和上次IO给出扇区地址相差比较大,这样的话磁头在两次IO *** 作之间需要作比较大的移动动作才能重新开始读/写数据。

(2) 连续访问(Sequential Access)

相反的,如果当次IO给出的扇区地址与上次IO结束的扇区地址一致或者是接近的话,那磁头就能很快的开始这次IO *** 作,这样的多个IO *** 作称为连续访问。

(3) 以SQL Server数据库为例

数据文件,SQL Server统一区上的对象,是以extent(88k)为单位进行空间分配的,数据存放是很随机的,哪个数据页有空间,就写在哪里,除非通过文件组给每个表预分配足够大的、单独使用的文件,否则不能保证数据的连续性,通常为随机访问。

另外哪怕聚集索引表,也只是逻辑上的连续,并不是物理上。

日志文件,由于有VLF的存在,日志的读写理论上为连续访问,但如果日志文件设置为自动增长,且增量不大,VLF就会很多很小,那么就也并不是严格的连续访问了。

2 顺序IO和并发IO

(1) 顺序IO模式(Queue Mode)

磁盘控制器可能会一次对磁盘组发出一连串的IO命令,如果磁盘组一次只能执行一个IO命令,称为顺序IO;

(2) 并发IO模式(Burst Mode)

当磁盘组能同时执行多个IO命令时,称为并发IO。并发IO只能发生在由多个磁盘组成的磁盘组上,单块磁盘只能一次处理一个IO命令。

(3) 以SQL Server数据库为例

有的时候,尽管磁盘的IOPS(Disk Transfers/sec)还没有太大,但是发现数据库出现IO等待,为什么?通常是因为有了磁盘请求队列,有过多的IO请求堆积。

磁盘的请求队列和繁忙程度,通过以下性能计数器查看:

LogicalDisk/AvgDisk Queue Length

LogicalDisk/Current Disk Queue Length

LogicalDisk/%Disk Time

这种情况下,可以做的是:

(1) 简化业务逻辑,减少IO请求数;

(2) 同一个实例下,多个数据库迁移的不同实例下;

(3) 同一个数据库的日志,数据文件分离到不同的存储单元;

(4) 借助HA策略,做读写 *** 作的分离。

3 IOPS和吞吐量(throughput)

(1) IOPS

IOPS即每秒进行读写(I/O) *** 作的次数。在计算传送时间时,有提到,如果IO Chunk Size大的话,那么IOPS会变小,假设以100M为单位读写数据,那么IOPS就会很小。

(2) 吞吐量(throughput)

吞吐量指每秒可以读写的字节数。同样假设以100M为单位读写数据,尽管IOPS很小,但是每秒读写了N100M的数据,吞吐量并不小。

(3) 以SQL Server数据库为例

对于OLTP的系统,经常读写小块数据,多为随机访问,用IOPS来衡量读写性能;

对于数据仓库,日志文件,经常读写大块数据,多为顺序访问,用吞吐量来衡量读写性能。

磁盘当前的IOPS,通过以下性能计数器查看:

LogicalDisk/Disk Transfers/sec

LogicalDisk/Disk Reads/sec

LogicalDisk/Disk Writes/sec

磁盘当前的吞吐量,通过以下性能计数器查看:

LogicalDisk/Disk Bytes/sec

LogicalDisk/Disk Read Bytes/sec

LogicalDisk/Disk Write Bytes/sec

以上就是关于数据库的多表大数据查询应如何优化全部的内容,包括:数据库的多表大数据查询应如何优化、postgressql数据源怎么配置、磁盘读写和数据库读写哪个效率更高等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/9460879.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-28
下一篇 2023-04-28

发表评论

登录后才能评论

评论列表(0条)

保存