CPU使用率过高的常见原因

查询优化器会尽量从CPU,IO和内存资源成本最小的角度,找到最高效的数据访问方式。如果没有正确的索引,或者写的语句本身就会忽略索引,

又或者不准确的统计信息等情况下,查询计划可能不是最优的。

有些查询计划可能对只对某种条件下的查询是高效,而不是所有条件下都是。

缺失索引

索引的缺失,会导致查询处理的行数大大超出必要的行数,从而加重CPU和IO的负载。简单的例子:

SELECT  per .FirstName  ,
per.LastName ,
p.Name ,
p.ProductNumber ,
OrderDate ,
LineTotal ,
soh.TotalDue
FROM Sales.SalesOrderHeader AS soh
INNER JOIN Sales.SalesOrderDetail sod
ON soh.SalesOrderID = sod.SalesOrderID
INNER JOIN Production.Product AS p ON sod.ProductID = p.ProductID
INNER JOIN Sales.Customer AS c ON soh.CustomerID = c.CustomerID
INNER JOIN Person.Person AS per
ON c.PersonID = per.BusinessEntityID
WHERE LineTotal > 25000 SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 0 ms. SQL Server Execution Times:
CPU time = 452 ms, elapsed time = 458 ms.

上面的查询使用AdventureWorks2008数据库,字段LineTotal上没有索引,会导致SalesOrderDetail全表扫描。然后创建如下索引后,改善很明显:

CREATENONCLUSTEREDINDEX
idx_SalesOrde
ON
Sales.SalesOrderDetail (LineTotal)
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 0 ms. SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 8 ms.

过期的统计信息

查询优化器使用统计信息计算各种查询操作的基数(开销)。查询操作的成本(cost)又决定了查询计划的成本。过期的统计信息会导致生成非最优的查询计划,

如预估成本很低,但实际成本很高的计划。

最常见就是预估行数很少,并选择了那些适合少量数据的操作(如嵌套循环,LookUp),但当实际执行时要处理的行数却很多,查询效率就变得很低。

可以通过SSMS或者set statistics profile on为索引查找和扫描操作,返回实际行数与预估行数做比较。如果两者差异较大,就很有可能统计信息过期了。

过期时,可以使用update statistics tableName更新表上所有的统计信息,update statistics tableName statisticsName更新指定统计信息。

为了防止统计信息过期的问题,有如下三种方法:

a. 开启数据库的Auto_Update_Statistics选项或者用定时作业更新全库的统计信息。

b. 如果某些索引的自动更新统计信息被禁用,则需要指定STATISTICS_NORECOMPUTE=OFF重建索引开启。

c. 对于某些经常因为统计信息过期而导致性能问题的统计信息,可以创建定时作业频繁地更新它们。

非SAGR谓词

SAGR=Search Agrument.简单说就是能够使用索引查找的谓词。列应该直接与表达式进行比较则符合SAGR,如WHERE  SomeFunction(Column) = @Value就符合,

WHERE Column = SomeOtherFunction(@Value) 则符合。注意LIKE和BETWEEN也是SAGR谓词。

非SAGR会导致表或者索引扫描,它的影响跟缺失索引类似。使得CPU处理大量非必需的数据行。下面查询会导致索引扫描:

SELECT  soh .SalesOrderID ,
OrderDate ,
DueDate ,
ShipDate ,
Status ,
SubTotal ,
TaxAmt ,
Freight ,
TotalDue
FROM Sales.SalesOrderheader AS soh
INNER JOIN Sales.SalesOrderDetail AS sod
ON soh.SalesOrderID = sod.SalesOrderID
WHERE CONVERT(VARCHAR(10), sod.ModifiedDate , 101) = '01/01/2010'

改写成如下则会使用索引查找:

SELECT  soh .SalesOrderID ,
OrderDate ,
DueDate ,
ShipDate ,
Status ,
SubTotal ,
TaxAmt ,
Freight ,
TotalDue
FROM Sales.SalesOrderheader AS soh
INNER JOIN Sales.SalesOrderDetail AS sod ON soh.SalesOrderID = sod.SalesOrderID
WHERE sod.ModifiedDate >= '2010/01/01'
AND sod.ModifiedDate < '2010/01/02'

UPPER,LOWER,LTRIM,RTRIM,ISNULL这些经常会被滥用,甚至用于WHERE和JOIN条件中。

在不区分大小写排序规则中,大小写被视为相等的,像UPPER,LOWER这种拖累性能的函数就不必要用了。

SQL中字符串比较会忽略末尾空格,所以RTRIM也没必要用。

下面两个过滤条件,前者,字段NULL值转换成0从而被排除;后者中,其实NULL值与任何值比较操作都不会返回TURE,而被排除。

NULL值只在IS NULL或者IS NOT NULL检查时才可能返回TRUE。所以是等效的,但后者才能使用索引查找。

WHERE  ISNULL(SomeCol,0) > 0 
WHERE  SomeCol > 0

隐式转换

隐式转换发生在比较两个不同数据类型时。SQL不能对不同类型数据进行比较,所以查询优化器会在比较操作前把低优先级的数据类型转换成高优先级的数据类型再比较。

这跟非SARG谓词一样,将不能使用Index Seek,从而处理很多不必要的数据行,增加CPU开销。最常见例子是使用NVARCHAR类型的参数与VARCHAR类型的列进行比较。如:

 
SELECTp .FirstName , p.LastName , c.AccountNumber
FROM
Sales.Customer ASc
INNER JOINPerson.Person AS p
ON c.PersonID = p.BusinessEntityID
WHERE AccountNumber = N'AW00029594'
上面的查询导致一个非聚集索引扫描,在Filter操作中会看有一个COVERT_IMPLICIT。

为了避免隐式转换:

1. JOIN的列,数据类型尽量相同

2. 与列比较时,任何参数,变量和常量的类型要和列的类型相同

3. 当参数,变量或常量的类型与要比较的列不同时,斟酌地使用类型转换函数,使其与列类型相同

4. 有些数据访问组件和开发框架会把字符串类型默认地设置为NVARCHAR

参数探测(Parameter Sniffing)

参数探测是SQL Server为存储过程,函数和参数化查询创建查询计划时用到的处理方式。当首次编译查询计划时,SQL Server会检测或者探测输入参数的值并结合统计信

息,预估受影响的行数,

并以之估算查询计划成本。当根据传入的参数值创建查询计划,得到的受影响行数不是典型的情况时,就产生问题了。参数探测只出现在编译和重编译时,之后的存储过程,函数和

参数化查询,

会重用此查询计划。最初编译时只有输入参数的值会被探测到,本地变量是没有值的。如果批处理中的语句被重编译,则参数和变量将会被赋值并探测到。示例如下:


CREATEPROCEDUREuser_GetCustomerShipDates
( @ShipDateStart DATETIME
, @ShipDateEnd DATETIME
)
AS
SELECT CustomerID , SalesOrderNumber
FROM Sales.SalesOrderHeader
WHERE ShipDate BETWEEN @ShipDateStart AND @ShipDateEnd
GO
Sales.SalesOrderHeader表的ShipDate字段范围是2004-08-07~2011-08-07,并创建非聚集索引: 
CREATENONCLUSTEREDINDEX IDX_ShipDate_ASC
ON Sales.SalesOrderHeader (ShipDate )
GO
首先我们执行两次SP,并用DBCC FREEPROCCACHE在运行前清空计划缓存:
DBCC FREEPROCCACHE
EXEC user_GetCustomerShipDates '2001/07/08', '2004/01/01'
EXEC user_GetCustomerShipDates '2001/07/10', '2001/07/20'
查询计划如图: 
查询并没有使用ShipDate列非聚集索引,因为它不是一个覆盖索引,并且被执行时,查询优化器根据参数值结合统计信息预估的行数很多,使用IndexSeek和LookUp的组合成本
 
太高。再观察STATISTICS IO&TIME:
==FIRST EXECUTION (LARGE DATE RANGE)===  

(Table 'SalesOrderHeader'. Scan count 1, logical reads 686, physical reads 0.  

 SQL Server Execution Times:
CPU time = 16 ms, elapsed time = 197 ms. SQL Server Execution Times:
CPU time = 16 ms, elapsed time = 197 ms. ==SECOND EXECUTION (SMALL DATE RANGE)=== Table 'SalesOrderHeader'. Scan count 1, logical reads 686, physical reads 0. SQL Server Execution Times:
CPU time = 15 ms, elapsed time = 5 ms. SQL Server Execution Times:
CPU time = 15 ms, elapsed time = 5 ms.
两者的纯CPU时间和IO是基本一样,因为前者需要处理的数据量多很多,所以CPU消耗时间长一些。接下来,调换两个执行SP的顺序,再执行:
DBCC FREEPROCCACHE
EXEC user_GetCustomerShipDates '2001/07/10', '2001/07/20'
EXEC user_GetCustomerShipDates '2001/07/08', '2004/01/01'
==FIRST EXECUTION (SMALL DATE RANGE)===  

Table 'SalesOrderHeader'. Scan count 1, logica
ahead reads 0, lob logical reads 0, lob physic SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 0 ms. ==SECOND EXECUTION (LARGE DATE RANGE)=== Table 'SalesOrderHeader'. Scan count 1, logica SQL Server Execution Times:
CPU time = 47 ms, elapsed time = 182 ms.
这次两者性能差距就很明显了。参数探测导致优化器采用了适合少量数据的KeyLookUp操作,而第二次查询重用了此查询计划,但是实际它需要处理大量数据,
 
这时KeyLookUp就导致了明显的性能问题,需要额外的IO和CPU资源。 
 
根据具体的环境和SQL Server版本,有多种处理参数探测的方法:
1. 跟踪标志4136
      此跟踪标志使得SQLServer实例不再使用参数探测,而是使用列平均重复个数(=总行数/列的非重复值个数)来估算受影响行数。 这样的估算值是不精确的。
 
启用此标志将会使得那些正确的参数探测的情况,变得不准确,带来负面影响。所以应该做为最后的手段。
 
适用于SQL Server 2008 SP1 CU7,SQL Server 2008 R2 CU2,SQL Server 2005 in SP3 CU9。 
 
2. 使用OPTIMIZE FOR查询提示 SQLServer 2005及后续版本中,可以为查询优化器编译查询计划时指定参数的值。如:
CREATE PROCEDURE user_GetCustomerShipDates
(
@ShipDateStart DATETIME ,
@ShipDateEnd DATETIME
)
AS
SELECT CustomerID ,
SalesOrderNumber
FROM Sales.SalesOrderHeader
WHERE ShipDate BETWEEN @ShipDateStart AND @ShipDateEnd
OPTION ( OPTIMIZE FOR ( @ShipDateStart = '2001/07/08' ,
@ShipDateEnd = '2004/01/01' ) )
GO
在2008中还能OPTIMIZE FOR UNKNOWN使得优化器不用参数探测,这个跟T-4136一样,只不过是语句级。
        
3. 重编译选项   

在创建存储过程可以指定WITH RECOMPILE重编译选项。指定后SP每次执行时会基于当前参数值重新编译,同时也不缓存执行计划。但是这样会增加执行处理时间。

CREATE PROCEDURE user_GetCustomerShipDates
(
@ShipDateStart DATETIME ,
@ShipDateEnd DATETIME
)
WITH RECOMPILE
AS
SELECT CustomerID ,SalesOrderNumber
FROM Sales.SalesOrderHeader
WHERE ShipDate BETWEEN @ShipDateStart AND @ShipDateEnd

当SP中的多个语句,只是某个语句会产生参数探测问题,则可以对这个语句使用OPTION(RECOMPILE)查询提示。这样每次执行时只会对这个语句重编译,

而不像WITH RECOMPILE对整个SP重编译。如果可能尽量使用查询提示,减少重编译的影响范围和开销。

CREATE PROCEDURE user_GetCustomerShipDates
(
@ShipDateStart DATETIME ,
@ShipDateEnd DATETIME
)
AS
SELECT CustomerID ,
SalesOrderNumber
FROM Sales.SalesOrderHeader
WHERE ShipDate BETWEEN @ShipDateStart AND @ShipDateEnd
OPTION ( RECOMPILE )
 
即席非参数化查询
    即席查询不能重用执行计划,每次执行时都会被编译,消耗大量资源(特别是CPU)。像下面的查询,每次因为WHERE条件中参数值不同而产生不同的执行计划。
    虽然SQL Server有简单参数化(Simple Parameterization)的技术,但是此语句相对”太复杂”了。
SELECT  soh .SalesOrderNumber  ,
sod.ProductID
FROM Sales.SalesOrderHeader AS soh
INNER JOIN Sales.SalesOrderDetail AS sod
ON soh.SalesOrderID = sod.SalesOrderID
WHERE soh.SalesOrderNumber = 'SO43662'
    非参数化查询主要有两方面的影响:
        1. 即席查询产生的一次性的查询计划会填满计划缓存。由此带来的内存压力,会让那些本可以重用的计划迫于内存压力而被清除掉等等。
        2. 编译这些一次性的查询计划浪费了大量的CPU资源。
    可以用下面的计数器来判断即席非参数化查询的影响程度: 

SQLServer: SQL Statistics: SQL Compilations/Sec
SQLServer: SQL Statistics: Auto-Param Attempts/Sec
SQLServer: SQL Statistics: Failed Auto-Param/Sec

解决的方法有:

1. 修改应用程序代码,使发送到SQL Server语句尽量被参数化。

2. 在SQL Server 2005及以上版本中,能在数据库级别设定强制参数化。但可能会带来类型参数探测一样的问题。

ALTER  DATABASE  AdventureWorks SET  PARAMETERIZATION FORCED
 3. SQL Server 2008及以上版本中,启用实例级别的optimize for  ad hoc  workloads。
        启用后当即席查询第一次执行时只保存查询计划的一个“存根”,第二次执行时则缓存执行计划。“存根”使用很少的内存,
        这样就减少了那些本可以重用的执行计划,因内存压力而被清除掉的机率。
EXEC sp_configure  'show advanced options',1
RECONFIGURE
EXEC sp_configure 'optimize for ad hoc workloads',1
RECONFIGURE
不恰当的并行
   并行查询是把一个查询的工作分解成多个线程执行,每一个线程使用单独的计划程序。查询并行发生在操作符(Operator)级别。
查询优化器在编译执行计划时总是会让其尽可能的快。如果执行计划的预估成本连续超过cost threshold of prillelism,同时SQL Server可用
CPU个数多于1个,并且max degree of prallelism为0或大于1,则产生的执行计划将会包括并行。
并行查询通过水平分割输入数据,然后分布到多个逻辑CPU上同时执行,从而减少执行时间。对于数据仓库和报表系统会有好处,对于OLTP系统
则并行会占用过多的CPU资源,而其它的请求不得不等待CPU资源。
SQL Server有两个控制并行执行的sp_configure选项:
   cost threshold of prillelism:控制优化器为查询使用并行执行的阀值
   max degree of prallelism:避免单个查询用完所有可用的处理器内核
 cost threshold of prallelism的默认值为5秒。在较大的数据库上,默认阀值可能太低了,会导致并行执行的资源争用。
 可以通过下面的查询获取存于计划缓存中的并行执行计划,做为调整cost threshold of prillelism的重要参考依据:
SET  TRANSACTION ISOLATION LEVEL  READ UNCOMMITTED ;  

WITH XMLNAMESPACES
(DEFAULT 'http://schemas.microsoft.com/sqlserver/2004/07/showplan')
SELECT query_plan AS CompleteQueryPlan ,
n.value ('(@StatementText)[1]', 'VARCHAR(4000)' ) AS StatementText ,
n.value ('(@StatementOptmLevel)[1]', 'VARCHAR(25)')
AS StatementOptimizationLevel ,
n.value ('(@StatementSubTreeCost)[1]', 'VARCHAR(128)')
AS StatementSubTreeCost ,
n.query ('.' ) AS ParallelSubTreeXML ,
ecp.usecounts ,
ecp.size_in_bytes
FROM sys .dm_exec_cached_plans AS ecp
CROSS APPLY sys .dm_exec_query_plan(plan_handle) AS eqp
CROSS APPLY query_plan.nodes
('/ShowPlanXML/BatchSequence/Batch/Statements/StmtSimple')
AS qn ( n )
WHERE n.query ('.' ).exist ('//RelOp[@PhysicalOp="Parallelism"]' ) = 1
 
并行中使用到处理器数是取自后面三者中的最小值:max degree of prallelis的值,可用的处理器数和MAXDOP查询提示(会覆盖max degree of prallelis指定的值)。
合适的max degree of prallelis值取决于工作负载类型和硬件资源支撑并行开销的能力。很多砖家推荐将其设定为1,前提是你的系统是真正的单独的OLTP系统,
只有大量的并发的小事务。对于NUMA和SMP系统的设定是不同的。SQL Server 2008及以上版本利用resource governor能将max degree of prallelis绑定到特定的查询组。
 
当系统出现并行性能问题时,通常会CXPACKET等待会比较明显,其实它很冤,它只是个表面现象。根本原因还是要查看产生CXPACKET等待的子线程的等待类型。
如果伴随着如IO_COMPLETION,ASYNC_IO_COMPLETION,PAGEIOLATCH_*的等待,则要提高IO性能;
如果伴随着LATCH_*  and SOS_SCHEDULER_YIELD,则表示并行本身导致了性能问题,如果此时还有ACCESS_METHODS_DATASET_PARENT等待,则执行的并行度是根本原因。
出现这些问题时首先应该优化并行执行的语句,其次才是结合max degree of prallelis和cost threshold of prillelism两者进行限制,再次是提升硬件。
在硬件暂时无法提升时,只能对并行做一定限制,做折中和权衡考量。
 
在SQL Server 2005,有个关于TokenAndPermUserStore的CPU问题。当数据库用户很多,adhoc和动态查询很多且非AWE内存空间很多时,

可能会出现CMEMTHREAD大量等待和TokenAndPermUserStore使用过量并持续增长。微软已经推出的解决方案http://support.microsoft.com/kb/927396
长期的解决方案是修改程序架构,尽量减少可能导致此问题的adhoc和动态查询的使用。
短期解决方案是:
   1. 给应用程序账户提升为sysadmin,从而规避权限检查而极大的减少TokenAndPermUserStore的缓存使用量。这是有安全风险的
   2. 使用DBCC FREESYSTEMCACHE ('TokenAndPermUserStore'),定期清理这一部分缓存。
   3. SQL Server 2005 SP2及以上版本,可以使用Trace Flag 4618&4610.4610限制缓存条目为1024,两者都启用则限制缓存条目为8192.
   4. SQL Server 2005 SP3及以上版本,使用Trace Flag 4621,可以设定缓存配额。 http://support.microsoft.com/kb/959823。
   5. SQL Server 2008有access check cache bucket count & access check cache quota两个sp_configure项,
      用于设置TokenAndPermUserStore的hash bucket数量和缓存条目数。
 
关于超线程和BIOS节能控制选项
   很多砖家推荐SQL Server服务器不宜开启超线程,根据作者的研究,这种推荐做法在过去是对的,现在不一定是对的。
在过去,超线出来的CPU会一起共享板载缓存,而这个缓存是KB量级的。而且windows 2000本身不支持超线程,“超”出来的它会认为是物理CPU。“CPU”一多就会造成缓存命中率低下,进而影响性能。

而很多DBA管理的OLTP&DSS的混合环境,那么超线程对于那些DSS型查询的提升,在混合环境中很不明显,甚至有时会导致需要迅速响应OLTP弄查询等待。
现在,硬件和软件进步了,现在板载缓存量级都是MB级的了,CPU缓存命中率不再是问题。而windows 2003也支持超线程了。而且现在OLTP,OLAP,DW等系统一般会隔离使用。
当然是否开启还是需要经过测试才能最终决定。
 
绿色节能现在也是硬件和服务器一种标准了,自动降低系统中某些暂时未用到的硬件能耗和CPU频率。BioS中可以设定为硬件自己控制或者OS控制。
windows 2008&r2默认设定电源计划为“平衡”,以允许其切换到节能模式。有时在windows 2008 or R2的新服务器升级系统一段时间后,性能下降明显,这就是电源管理造成的CPU降频导致的。
windows的性能计数器 % Processor Usage 是已使用CPU频率除以可用CPU频率得到的。如果CPU被降频了,那么这个计算器会较高,会让人误会成工作负载很高。
可以使用CPU-Z来检测CPU的状态。
建议将windows的电源计划调定为“高性能”,并且检查BIOS的电源控制选项,设定为OS Control.
 
总结:
   1. SQL SERVER CPU调整的地方很少,很多时候还是因为语句性能低下导致CPU使用过高。
   2. 解决参数嗅探问题,还有拼动态语句,使用plan_guide等方法。
来源:http://www.cnblogs.com/Joe-T/p/3261177.html

数据库性能高校:CPU使用过高(下)的更多相关文章

  1. 数据库性能高校:CPU使用过高(上)

    CPU使用率过高问题很容易被发现,但是诊断却不是很容易.CPU使用过高很多时候会成为其它问题的替罪羊,所以在确认和故障诊断时要抽丝剥茧. 调查CPU压力 三个主要的工具:性能监视器,SQLTrace, ...

  2. 性能测试问题_Mysql数据库服务器的CPU占用很高

    MySQl服务器CPU占用很高 1.  问题描述 一个简单的接口,根据传入的号段查询号码归属地,运行性能测试脚本,20个并发mysql的CPU就很高,监控发现只有一个select语句,且表建立了索引 ...

  3. 性能优化-CPU占用过高问题排查

    1. 性能优化是什么? 1.1 性能优化就是发挥机器本来的性能 1.2 性能瓶颈在哪里,木桶效应.   CPU占用过高 1.现象重现 CPU占用过高一般情况是代码中出现了循环调用,最容易出现的情况有几 ...

  4. 《Troubleshooting SQL Server》读书笔记-CPU使用率过高(下)

    <Troubleshooting SQL Server>读书笔记-CPU使用率过高(下) 第三章 High CPU Utilization. CPU使用率过高的常见原因 查询优化器会尽量从 ...

  5. [Oracle]Oracle数据库CPU利用率很高解决方案

    Oracle数据库经常会遇到CPU利用率很高的情况,这种时候大都是数据库中存在着严重性能低下的SQL语句,这种SQL语句大大的消耗了CPU资源,导致整个系统性能低下.当然,引起严重性能低下的SQL语句 ...

  6. 性能分析(5)- 软中断导致 CPU 使用率过高的案例

    性能分析小案例系列,可以通过下面链接查看哦 https://www.cnblogs.com/poloyy/category/1814570.html 前言 软中断基本原理,可参考这篇博客:https: ...

  7. Linux下java进程CPU占用率高分析方法

    Linux下java进程CPU占用率高分析方法 在工作当中,肯定会遇到由代码所导致的高CPU耗用以及内存溢出的情况.这种情况发生时,我们怎么去找出原因并解决. 一般解决方法是通过top命令找出消耗资源 ...

  8. 性能调优之MYSQL高并发优化下

    三.算法的优化 尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该考虑改写..使用基于游标的方法或临时表方法之前,应先寻找基于集的解决方案来解决问题,基于集的方法通常更有效 ...

  9. Linux下分析某个进程CPU占用率高的原因

      Linux下分析某个进程CPU占用率高的原因 通过top命令找出消耗资源高的线程id,利用strace命令查看该线程所有系统调用  1.top 查到占用cpu高的进程pid 2.查看该pid的线程 ...

随机推荐

  1. Ajax长连接应用

    所谓的长连接,就是不断去发送请求,把请求阻塞在服务器端,每次超过请求时间就去重新发送请求,保持连接,随时获取服务器端的响应的数据 function connection(){ $.ajax({ typ ...

  2. 拷贝出你GAC里面的DLL文件

    转:http://blog.sina.com.cn/s/blog_573be9bc0100ht65.html 早上和同事探讨如何从GAC中拷贝已经部署的DLL文件的时候,除了以前熟悉的命令行拷贝方法, ...

  3. ecshop模板修改后还原的原因

    转:http://www.ecmoban.com/article-1693.html 有些刚接触 ecshop的朋友会遇到这样的问题:今天刚修改好的一个地方,等过一段时间后台操作了一会之后发现修改过的 ...

  4. Tree HDOJ--2682

    Tree Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  5. [转]NHibernate之旅(6):探索NHibernate中的事务

    本节内容 事务概述 1.新建对象 [测试成功提交] [测试失败回滚] 2.删除对象 3.更新对象 4.保存更新对象 结语 上一篇我们介绍了NHibernate中的Insert, Update, Del ...

  6. Unity3d 模拟视锥的实现

    一个独立游戏 Teleglitch 使用了一种欺骗手法来模拟视锥,效果如下: 博主看了看了看提示 Actually, the line of sight shadows aren’t done wit ...

  7. 《C语言程序设计现代方法》第2章 编程题

    7 编写一个程序,要求用户输入一个美金数量,然后显示出如何使用最少的20美元.10美元.5美元和1美元来付款. 提示:将付款金额除以20,确定20美元的数量,然后从付款金额中减去20美元的总金额.对其 ...

  8. js 打印网页指定内容

    function doPrint() { setTimeout(function() { bdhtml=window.document.body.innerHTML; sprnstr="&l ...

  9. Bzoj 1853: [Scoi2010]幸运数字 容斥原理,深搜

    1853: [Scoi2010]幸运数字 Time Limit: 2 Sec  Memory Limit: 64 MBSubmit: 1774  Solved: 644[Submit][Status] ...

  10. Java学习感受

    一个暑假,两本书,让我了解到了Java的神奇美妙,这个工具的年龄跟我一样大,然而日久弥新,随着电脑技术科学家,工程师的开发,Java的功能越来越完善.学习的时间不长,但我比较着学习,把Java跟C.C ...