SQL性能调优实践——SELECT COUNT

简介: 最近想深入学习SQL,在网上搜索到一些SQL 优化的资料要么是张冠李戴,Oracle 优化的资料硬是弄成啦MS SQL 优化的资料,而且被很多人转载,收藏,有些要么有些含糊不清,好像是那么回事,也没经过验证,实践出真知!下面是我对SELECT COUNT(*), SELECT COUNT(1),SELECT COUNT (0), SELECT COUNT(Field)等孰优孰劣的测试结果,如果测试方法有什么不足,也希望大家给点建议。

最近想深入学习SQL,在网上搜索到一些SQL 优化的资料要么是张冠李戴,Oracle 优化的资料硬是弄成啦MS SQL 优化的资料,而且被很多人转载,收藏,有些要么有些含糊不清,好像是那么回事,也没经过验证,实践出真知!下面是我对SELECT COUNT(*) SELECT COUNT(1)SELECT COUNT (0), SELECT COUNT(Field)等孰优孰劣的测试结果,如果测试方法有什么不足,也希望大家给点建议。

 

首先我们来看看测试的机器、以及开发环境吧:双核处理器 T6670  2G DDR2的内存 数据版本如下图所示:

 

 然后建一个简单的测试表

CREATE TABLE Employee
(
    [EmployeeID]        INT IDENTITY(1,1),  --雇员ID
    [EmployeeName]      NVARCHAR(20)     ,  --雇员姓名
     [SEX]               BIT              ,  --性别
     [Department]        NVARCHAR(20)     ,  --部门
     CONSTRAINT [PK_Employee_ID_Name] PRIMARY KEY (EmployeeID, EmployeeName) 
)
 
--插入一百万数据
 
DECLARE @Index INT;
SET @Index = 1;
WHILE @Index < 1000000
BEGIN
    INSERT INTO Employee
    VALUES('Employee' + STR(@Index), '0', '技术部门');
    
    SET @Index = @Index + 1;
END
 
--建立非聚集索引
CREATE INDEX IDX_Employee_Department ON Employee([Department]);
 

好,到目前为止我们已经把测试用的表、数据都弄好啦,接下来我们来看看执行一次SELECT COUNT 的使用时间

Code Snippet
  1. DBCC DROPCLEANBUFFERS;
  2.  
  3. DBCC FREEPROCCACHE;
  4.  
  5. SET STATISTICS TIME ON;
  6.  
  7. SELECT COUNT(0) FROM Employee
  8.  
  9. SET STATISTICS TIME OFF;

 

我们会得到下面的输出结果

DBCC 执行完毕。如果DBCC 输出了错误信息,请与系统管理员联系。

DBCC 执行完毕。如果DBCC 输出了错误信息,请与系统管理员联系。

 

SQL Server 执行时间:

   CPU 时间= 219 毫秒,占用时间= 1033 毫秒。 

接下来我们来看看各种Count的实际执行计划,截图如下

 

我很纳闷为什么执行计划都是一样的,希望有高手能解答。

接下来,那么我们把上面的脚本执行10,把每次得到的数据记录下来,然后我们依次用

SELECT COUNT(1) FROM Employee、 SELECT COUNT(*)  FROM Employee

等替换SELECT COUNT(0) FROM Employee 脚本,如下所示

DBCC DROPCLEANBUFFERS;
 
DBCC FREEPROCCACHE;
 
SET STATISTICS TIME ON;
 
SELECT COUNT(1) FROM Employee
 
SET STATISTICS TIME OFF; 
 

依葫芦画瓢每段脚本执行10次,最后我们求得到的结果的平均值,为了形象显示,我用Excel把数据显示如下: 

 SELECT COUNT(1) FROM Employee

 

SELECT COUNT(0) FROM Employee

 

SELECT COUNT(*) FROM Employee

 

SELECT COUNT(EmployeeName) FROM Employee

 

从实验结果来看,执行快慢的顺序为: COUNT(EmployeeName) > COUNT(0) ~= COUNT(1) > COUNT(*);从实验结果来看,我们至少验证了 COUNT(0) ~= COUNT(1) > COUNT(*)的结论,网上有篇帖子《SQL Server 索引结构及其使用》篇所下的结论count(*)不比count(字段)慢 显然是不严谨的,他只做了一次实验,而我们这里是10次结果的平均值。那么现在问题来了,为什么COUNT(EmployeeName)要快于COUNT(0) >= COUNT(1),它如果不是主键、字段没有索引呢?网上不是有些资料显示COUNT(1)效率最高,速度最快吗? 我们10次得到平结值有没有误差呢?抽样能否反映事实呢?下面我用这个方法来大量获得语句执行时间,然后求平均值,(我觉得这方法应该是可以反映实际CPU时间的)如果有不妥的地方,也希望大家指正。 创建下面一个表

CREATE TABLE ExcuteTime
(
    [Type]     VARCHAR(10),    --不同COUNT类型
     [CpuTime]    FLOAT         --语句执行的毫秒
)
--得到COUNT(1)100次的执行时间
DECLARE @BeginTime DATETIME;
DECLARE @Num INT;
SET @Num = 1;
WHILE @Num <= 100
BEGIN
SET @BeginTime = GETDATE();
SELECT COUNT(1) FROM Employee;
INSERT INTO ExcuteTime
VALUES('Count(1)', DATEDIFF(ms, @BeginTime,GETDATE()));
SET @Num = @Num + 1;
END
GO

 

然后也依次得到其它几种SQl 的执行时间,另外我们也把COUNT(Department)得数据加入进来,下面是我得到的实验结果的平均值

COUNT(1) COUNT(0) COUNT(*) COUNT(EmployeeName) COUNT(Department)
100.09 99.27 100.28 65.95 134.13
      

 

    

 

数据显示也与上面的测试结果相一致,虽然得到了这些结果,由于统计偏差缘故,COUNT(0)比 COUNT(1) 稍稍快些,这个是完全可以忽略,因为我统计的次数比小,很容易造成偏差,COUNT(*) 接近于COUNT(1),估计是由于数据缓存缘故,其实我们从实验结果可以看出统计数据的速度: 对索引字段统计要快于COUNT(1),原因是COUNT(1)是要走全表扫描,而COUNT(1) 快于COUNT(*) ,是因为COUNT(*)走全表扫描的开销要大于COUNT(1), 至于统计非索引字段COUNT(Department),比较偏大的,则让我有点纳闷,估计是统计偏差缘故。










相关文章
|
8月前
|
SQL Java 关系型数据库
在 RDB 上跑 SQL------SPL 轻量级多源混算实践 1
SPL 支持通过 JDBC 连接 RDB,可动态生成 SQL 并传参,适用于 Java 与 SQL 结合的各类场景。本文以 MySQL 为例,演示如何配置数据库连接、编写 SPL 脚本查询 2024 年订单数据,并支持参数过滤和 SQL 混合计算。脚本可在 IDE 直接执行或集成至 Java 应用调用。
|
11月前
|
SQL 存储 关系型数据库
SQL优化策略与实践:组合索引与最左前缀原则详解
本文介绍了SQL优化的多种方式,包括优化查询语句(避免使用SELECT *、减少数据处理量)、使用索引(创建合适索引类型)、查询缓存、优化表结构、使用存储过程和触发器、批量处理以及分析和监控数据库性能。同时,文章详细讲解了组合索引的概念及其最左前缀原则,即MySQL从索引的最左列开始匹配条件,若跳过最左列,则索引失效。通过示例代码,展示了如何在实际场景中应用这些优化策略,以提高数据库查询效率和系统响应速度。
479 10
|
7月前
|
SQL 关系型数据库 Java
SQL 移植--SPL 轻量级多源混算实践 7
不同数据库的 SQL 语法存在差异,尤其是函数写法不同,导致 SQL 移植困难。SPL 提供 sqltranslate 函数,可将标准 SQL 转换为特定数据库语法,实现 SQL 语句在不同数据库间的无缝迁移,支持多种数据库函数映射与自定义扩展。
|
11月前
|
SQL 安全 关系型数据库
SQL注入之万能密码:原理、实践与防御全解析
本文深入解析了“万能密码”攻击的运行机制及其危险性,通过实例展示了SQL注入的基本原理与变种形式。文章还提供了企业级防御方案,包括参数化查询、输入验证、权限控制及WAF规则配置等深度防御策略。同时,探讨了二阶注入和布尔盲注等新型攻击方式,并给出开发者自查清单。最后强调安全防护需持续改进,无绝对安全,建议使用成熟ORM框架并定期审计。技术内容仅供学习参考,严禁非法用途。
1684 0
|
5月前
|
SQL 关系型数据库 MySQL
为什么这些 SQL 语句逻辑相同,性能却差异巨大?
我是小假 期待与你的下一次相遇 ~
256 0
|
8月前
|
SQL
SQL中搜索中文无效或Select中文变乱码
SQL中搜索中文无效或Select中文变乱码
|
7月前
|
SQL 人工智能 数据挖掘
如何在`score`表中正确使用`COUNT`和`AVG`函数?SQL聚合函数COUNT与AVG使用指南
本文三桥君通过score表实例解析SQL聚合函数COUNT和AVG的常见用法。详解COUNT(studentNo)、COUNT(score)、COUNT()的区别,以及AVG函数对数值/字符型字段的不同处理,特别指出AVG()是无效语法。实战部分提供6个典型查询案例及结果,包含创建表、插入数据的完整SQL代码。产品专家三桥君强调正确理解函数特性(如空值处理、字段类型限制)对数据分析的重要性,帮助开发者避免常见误区,提升查询效率。
393 0
|
9月前
|
SQL 关系型数据库 PostgreSQL
CTE vs 子查询:深入拆解PostgreSQL复杂SQL的隐藏性能差异
本文深入探讨了PostgreSQL中CTE(公共表表达式)与子查询的选择对SQL性能的影响。通过分析两者底层机制,揭示CTE的物化特性及子查询的优化融合优势,并结合多场景案例对比执行效率。最终给出决策指南,帮助开发者根据数据量、引用次数和复杂度选择最优方案,同时提供高级优化技巧和版本演进建议,助力SQL性能调优。
990 1
|
11月前
|
SQL 关系型数据库 MySQL
大数据新视界--大数据大厂之MySQL数据库课程设计:MySQL 数据库 SQL 语句调优方法详解(2-1)
本文深入介绍 MySQL 数据库 SQL 语句调优方法。涵盖分析查询执行计划,如使用 EXPLAIN 命令及理解关键指标;优化查询语句结构,包括避免子查询、减少函数使用、合理用索引列及避免 “OR”。还介绍了索引类型知识,如 B 树索引、哈希索引等。结合与 MySQL 数据库课程设计相关文章,强调 SQL 语句调优重要性。为提升数据库性能提供实用方法,适合数据库管理员和开发人员。
|
11月前
|
关系型数据库 MySQL 大数据
大数据新视界--大数据大厂之MySQL 数据库课程设计:MySQL 数据库 SQL 语句调优的进阶策略与实际案例(2-2)
本文延续前篇,深入探讨 MySQL 数据库 SQL 语句调优进阶策略。包括优化索引使用,介绍多种索引类型及避免索引失效等;调整数据库参数,如缓冲池、连接数和日志参数;还有分区表、垂直拆分等其他优化方法。通过实际案例分析展示调优效果。回顾与数据库课程设计相关文章,强调全面认识 MySQL 数据库重要性。为读者提供综合调优指导,确保数据库高效运行。