如何编写高效的SQL查询语句

概述

如何编写性能比较高的SQL查询语句呢?两个方法:创建合理的索引;书写高效的SQL语句

索引的基本原理

索引分为聚集索引和非聚集索引。一个表只能创建一个聚集索引和N个非聚集索引,这句话的由来主要是由于索引的原理决定的。

数据库中的一张表不论你创建不创建索引,或者,不论你创建那种类型的索引,其在硬盘上的存储是一样的,那么,创建索引和不创建索引,或者,创建聚集索引和非聚集索引的区别在什么地方呢?

其区别是表内数据在内存的存在形式。对于没有创建索引的表,其加载到内存里时,就只有数据块;对于有聚集索引的表,其加载到内存时,会形成一棵树,且叶子节点上就是具体的数据;对于非聚集索引的表(没有聚集索引时),其加载内存时,真实数据为一个独立的块,其索引会形成一个索引树,索引数据的叶子节点对应的是真实数据块的rowid;对于既有非聚集索引,又有聚集索引的表,其加载到内存时,会形成两棵树,具体的数据和聚集索引树在一起,非聚集索引独自有一棵树,此时需要注意,其叶子节点中存放的时聚集索引的index,然后,通过聚集索引的index再去,聚集索引树中找到具体的数据。这个就是为什么一个表只能有一个聚集索引,可以有多个非聚集索引的原理。

如何知道我们的SQL查询语句执行时性能的好坏呢?

我们写一个SQL查询语句,怎么样才能知道这个SQL查询语句是好的还是坏的?

一种方法,我们大家都知道,直接在SQL Server的查询器中执行,然后,其执行状态栏会给出我们相应的结果,如:执行时间(秒);另一种方法,通过执行set statistics io on,开启资源消耗信息,执行set statistics time on,开启执行时间,开启这两个功能后,我们再次运行sql语句时,其结果视图旁边的消息视图内,会出现相应的结果;还有一种方式就是使用SQL Server Profiler工具(工具—SQL
Server Profiler),帮助我们监听执行的SQL语句的执行情况,这种方式更适用于我们在程序中无法提取SQL语句的情况。

怎样创建合理的索引?

通过上面的方法,我们可以知道我们的SQL语句的好坏,对于坏的SQL,我们要想法设法的进行相应的改变,但是,对于坏的SQL语句,我们在优化的时候,总得要知道其问题出在了哪里吧,不能说我就那么的改了,所以,此时,我们需要了另一个工具,帮助我们分析,即:执行计划视图(查询—显示执行的查询计划),通过执行计划,可知道我们SQL语句在执行查询的时候,使用了还是没有使用索引。在这里介绍3中查询的方式:table
scan,index scan,index seek。

table scan就是全表扫描,直接在真实的数据块中进行全部扫描;index scan就是在索引树上进行全扫描,此时如果是聚集索引,就会直接得到相应的数据(叶子上就是具体的数据),如果是非聚集索引,则需要获得叶子上相应的聚集索引键,然后,再根据聚集索引键在聚集索引树中找到相应的真实数据;index scan就是索引树上的搜索,这种方式的实现跟其内部的原理有关,因为这个是树,所以,根据一些算法(二叉等等)可以快速的定位到具体的数据,这个也分为聚集和非聚集,在这里不再赘述。

通过执行计划,我们可以知道,我们的SQL语句在那块没有使用索引,然后,我们可以改SQL语句,也可以创建相应的索引,这里需要知道,并不是使用了索引就一定块,如果你的数据非常的小,如果你创建的索引非常的多,那么,可能会存在这种情况:不如全表索引的块。所以,在优化我们的SQL时,我们尽量往已有的索引上靠拢,实现不行了,那么,根据数据量的多少,我们看看,是否需要再创建相应的索引。

怎么样才能书写高效的SQL查询语句?

上面一块内容我们知道了,我们的SQL语句应该尽可能的向已有的索引靠拢,那么,如果才能使用到已有的索引呢?你可能会说,我们多创建一些索引不就行了嘛,实在不行每个列都是一个索引,这样不就可以使用到了索引了嘛,按照你说的这种情况,我们姑且不考虑其它,就认为SQL语句执行的时候,使用了索引就是快,但是,我想说的是,及时你每个列上都创建上索引,也不见得你写的SQL语句在执行的时候就是使用到了index seek,为什么呢?因为系统在分析你的SQL语句时,无法找到一个合理的index
seek的执行计划,那么,怎么样写我们的SQL语句,才可以使系统经过分析后,得到的执行计划里使用到了index seek呢?怎么样写我们的SQL语句才可以得到最优的执行计划呢?

1、查询列的优化

用到表中的那个列就select谁,不要select * ,除非你每个列都使用,因为select * 和select 所有列是一样的

2、where查询条件的优化

不要对条件列进行相应的操作,如:在列上使用函数,列进行数据类型的转换,列上使用参数运算符(filed + ‘aaa‘),在列上使用不可参数化的条件(like ‘%a‘,not……,or……等),这些都会使索引的实现大大折扣,或者直接就丧失

3、其它

不要使用游标,可以使用集合条件查询代码游标;使用exists代替count(*)进行数据存在与否的验证

总结

索引多了不见得好,没有索引不见得不好;索引的有无,是根据具体的数据量来说的;该列是否要建立索引,是根据这个列在查询时作为条件查询的比重;好的SQL语句,不仅要向索引靠拢,也要屏蔽不必要的数据和执行次数。

如何编写高效的SQL查询语句,布布扣,bubuko.com

时间: 07-29

如何编写高效的SQL查询语句的相关文章

15个初学者必看的基础SQL查询语句

本文将分享15个初学者必看的基础SQL查询语句,都很基础,但是你不一定都会,所以好好看看吧. 1.创建表和数据插入SQL 我们在开始创建数据表和向表中插入演示数据之前,我想给大家解释一下实时数据表的设计理念,这样也许能帮助大家能更好的理解SQL查询. 在数据库设计中,有一条非常重要的规则就是要正确建立主键和外键的关系. 现在我们来创建几个餐厅订单管理的数据表,一共用到3张数据表,Item Master表.Order Master表和Order Detail表. 创建表: 创建Item Maste

没错,纯SQL查询语句可以实现神经网络

我们熟知的SQL是一种数据库查询语句,它方便了开发者在大型数据中执行高效的操作.但本文从另一角度嵌套SQL查询语句而构建了一个简单的三层全连接网络,虽然由于语句的嵌套过深而不能高效计算,但仍然是一个非常有意思的实验. 在这篇文章中,我们将纯粹用SQL实现含有一个隐藏层(以及带 ReLU 和 softmax 激活函数)的神经网络.这些神经网络训练的步骤包含前向传播和反向传播,将在 BigQuery 的单个SQL查询语句中实现.当它在 BigQuery 中运行时,实际上我们正在成百上千台服务器上进行

Hibernate 关于执行sql查询语句(转)

原文  http://www.yshjava.cn/post/543.html 主题 SQLHibernate Hibernate对原生SQL查询的支持和控制是通过SQLQuery接口实现的.通过Session接口,我们能够很方便的创建一个SQLQuery(SQLQuery是一个接口,在Hibernate4.2.2之前,默认返回的是SQLQuery的实现类--SQLQueryImpl对象,在下文中出现的SQLQuery如非注明,都是指该子类)对象来进行原生SQL查询: session.creat

将Sql查询语句获取的数据插入到List列表里面

Sql查询语句获取的数据是分格式的,我们还用SqlDataReader来做,然后用IDataReader来接收读取,以下是代码: //我想查询一个用户表的信息,该用户有姓名,密码,信息三列 //1.定义一个用户类型的List数组,userInfo类的代码在下方 List<userInfo> userInfo = new List<userInfo>(); //2.我们要读取查询语句的数据,并且保存了.这里我们将使用IDataReader语句 //数据库类的实例,类的代码在下方 DB

Java连接MySQL数据库实现用户名密码的验证方法 Java语句中sql查询语句&#39;&#39; &quot;&quot;作用

//方法一,可以验证登录,但方法不实用.package com.swift; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.List; public class Logi

SQL查询语句 group by后, 字符串合并

原文:SQL查询语句 group by后, 字符串合并 合并列值 --******************************************************************************************* 表结构,数据如下: id value ----- ------ 1 aa 1 bb 2 aaa 2 bbb 2 ccc 需要得到结果: id values ------ ----------- 1 aa,bb 2 aaa,bbb,ccc 即:gr

(转)经典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.说明:创建

Java 获取SQL查询语句结果

step1:构造连接Class.forName("com.mysql.jdbc.Driver"); Connection con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/db","root","123"); step2:构造语句String sql = "select username,password from t_user where

工作中常用SQL 查询语句备忘

--当A列大于B列时选择A列否则选择B列,当B列大于C列时选择B列否则选择C列.select (case when a>b then a else b end ), (case when b>c then b esle c end) from table_name --求和查询 create table #tmp(rq varchar(10), shengfu nchar(1)) insert into #tmp values('2005-05-09','胜') insert into #tm