sql组合索引
⑴ 试列举何种情况考虑创建索引,在sql中
转:
---使用索引优化数据库查询效率
1.不宜创建索引的情形
(1)经常插入,修改和删除的表
(2)数据量比较小的表,因为查询优化器在搜索索引时所花费的时间可能会大于遍历全表的数据所需要的时间
2.适合创建索引的情形
(1)为where子句中出现的列创建索引
(2)创建组合索引
(3)为group by 子句中出现的列创建索引
3.聚集索引的设计原则
(1)该列的数值是唯一的或者很少有重复的记录
(2)经常使用between ...and..按顺序查询的列
(3)定义identity的唯一列.
(4)经常用于对数据进行排序的列.
---无法使用索引的select语句
1.对索引列使用了函数,如:
select * from tb where max(id)=100
2.对索引列使用了'%xx',如:
select * from tb where id like '%1'
需要注意的不是所有使用like关键字的select 语句都无法使用索引,比如
select * from tb where id like '1%'就可以使用索引
3.在where子句中对列进行类型转换(其实也是使用到了函数)
4.在组合索引的第1列不是使用最多的列,如在下面3个查询语句中建立组合索引,按顺序包含col2,col1,id列;
select * from tb where id='1' and col1='aa'
select id,sum(col1) from tb group by id
select * from tb where id='2' and col2='bb'
则第一句和第二句无法使用到索引 所以需要注意组合索引的顺序
5.在where 子句中使用in关键字的某些句子
当在in关键字后面使用嵌套的select语句,将无法使用在该列上定义的索引
如:
select
*
from
ta
where
id
in
(select id from tb where ....)
--这样可以用到索引
select * from tb where id in('1','2')
⑵ mysql有几种索引类型使用索引时都有那些地方要注意sql优化原则是什么
mysql的索引类型及使用索引时的注意事项有:
一、普通索引。这是最基本的索引,它没有任何限制。它有以下几种创建方式:
1、创建索引
代码如下:
CREATE INDEX indexName ON mytable(username(length));
如果是CHAR,VARCHAR类型,length可以小于字段实际长度;如果是BLOB和TEXT类型,必须指定 length,下同。
2、修改表结构
代码如下:
ALTER mytable ADD INDEX [indexName] ON (username(length)) -- 创建表的时候直接指定
CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, INDEX [indexName] (username(length)) );
-- 删除索引的语法:
DROP INDEX [indexName] ON mytable;
二、唯一索引。它与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。它有以下几种创建方式:
代码如下:
CREATE UNIQUE INDEX indexName ON mytable(username(length))
-- 修改表结构
ALTER mytable ADD UNIQUE [indexName] ON (username(length))
-- 创建表的时候直接指定
CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, UNIQUE [indexName] (username(length)) );
三、主键索引。它是一种特殊的唯一索引,不允许有空值。一般是在建表的时候同时创建主键索引:
代码如下:
CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, PRIMARY KEY(ID) );
当然也可以用 ALTER 命令。记住:一个表只能有一个主键。
四、组合索引。为了形象地对比单列索引和组合索引,为表添加多个字段:
代码如下:
CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, city VARCHAR(50) NOT NULL, age INT NOT NULL );
为了进一步榨取MySQL的效率,就要考虑建立组合索引。就是将 name, city, age建到一个索引里:
代码如下:
ALTER TABLE mytable ADD INDEX name_city_age (name(10),city,age);[code]
建表时,usernname长度为 16,这里用 10。这是因为一般情况下名字的长度不会超过10,这样会加速索引查询速度,还会减少索引文件的大小,提高INSERT的更新速度。
如果分别在 usernname,city,age上建立单列索引,让该表有3个单列索引,查询时和上述的组合索引效率也会大不一样,远远低于我们的组合索引。虽然此时有了三个索引,但MySQL只能用到其中的那个它认为似乎是最有效率的单列索引。
建立这样的组合索引,其实是相当于分别建立了下面三组组合索引:usernname,city,age usernname,city usernname 为什么没有 city,age这样的组合索引呢?这是因为MySQL组合索引“最左前缀”的结果。简单的理解就是只从最左面的开始组合。并不是只要包含这三列的查询都会用到该组合索引,下面的几个SQL就会用到这个组合索引:
[code]
SELECT * FROM mytable WHREE username="admin" AND city="郑州" SELECT * FROM mytable WHREE username="admin"
⑶ Sql查询索引 (应该用组合索引)求教大神指教
索引一般分为聚集索引和非聚集索引,表的主键一般都是聚集索引,是自动创建的,而其他字段可以创建成为非聚集索引,索引相当于书本的目录,用于快速检索。创建方法如下:
CREATE NONCLUSTERED 索引名称 ON 表名(字段)
你上面的就是CREATE NONCLUSTERED INDEX_Staff_TypeId on Staff (TypeId)
CREATE NONCLUSTERED INDEX_Staff_mondId on Staff (mondId)
索引是你在查询的时候进行快速检索,是自动实现的,所以怎么使用就不用说了吧
⑷ sql server 2008单独索引与组合索引区别
首先要说明,不是所有的表都适合创建索引,因为索引需要占用一部分系统资源。
当你使用这个表的时候,如果该表的某个字段经常用来作为where条件判断,或者在做join联查的时候,该字段建议增加索引。
如果两个字段要一起参与where、join条件判断,建议创建组合索引。
⑸ sql索引分为几类
SQL SERVER中索引类型包括的三种类型分别是
唯一索引(UNIQUE),聚集索引(CLUSTERED) ,非聚集索引(NONCLUSTERED)。
主键与唯一索引的区别
主键是一种约束,唯一索引是一种索引,两者在本质上是不同的。 主键创建后一定包含一个唯一性索引,唯一性索引并不一定就是主键。 唯一性索引列允许空值,而主键列不允许为空值。 主键列在创建时,已经默认为空值 + 唯一索引了。
主键可以被其他表引用为外键,而唯一索引不能。 一个表最多只能创建一个主键,但可以创建多个唯一索引。 主键更适合那些不容易更改的唯一标识,如自动递增列、身份证号等。 在 RBO 模式下,主键的执行计划优先级要高于唯一索引。 两者可以提高查询的速度。
⑹ SQL中一个表可以有几个聚集索引或非聚集索引
一个表只能有一个聚集索引,可以有多个非聚集索引
下面是聚集索引和非聚集索引的详细介绍:
聚集索引基于数据行的键值在表内排序和存储这些数据行。每个表只能有一个聚集索引,因为数据行本身只能按一个顺序存储。有关聚集索引体系结构的详细信息,请参阅聚集索引结构。
每个表几乎都对列定义聚集索引来实现下列功能:
可用于经常使用的查询。
提供高度唯一性。
注意:
创建 PRIMARY KEY 约束时,将在列上自动创建唯一索引。默认情况下,此索引是聚集索引,但是在创建约束时,可以指定创建非聚集索引。
可用于范围查询。
如果未使用 UNIQUE 属性创建聚集索引,数据库引擎将向表自动添加一个 4 字节的 uniqueifier
列。必要时,数据库引擎将向行自动添加一个 uniqueifier 值以使每个键唯一。此列和列值供内部使用,用户不能查看或访问。
查询注意事项
在创建聚集索引之前,应先了解数据是如何被访问的。考虑对具有以下特点的查询使用聚集索引:
使用运算符(如 BETWEEN、>、>=、< 和
<=)返回一系列值。
使用聚集索引找到包含第一个值的行后,便可以确保包含后续索引值的行物理相邻。例如,如果某个查询在一系列销售订单号间检索记录,SalesOrderNumber
列的聚集索引可快速定位包含起始销售订单号的行,然后检索表中所有连续的行,直到检索到最后的销售订单号。
返回大型结果集。
使用 JOIN 子句;一般情况下,使用该子句的是外键列。
使用 ORDER BY 或 GROUP BY 子句。
在 ORDER BY 或 GROUP BY
子句中指定的列的索引,可以使数据库引擎不必对数据进行排序,因为这些行已经排序。这样可以提高查询性能。
列注意事项
一般情况下,定义聚集索引键时使用的列越少越好。考虑具有下列一个或多个属性的列:
唯一或包含许多不重复的值
例如,雇员 ID 唯一地标识雇员。EmployeeID 列的聚集索引或 PRIMARY KEY
约束将改善基于雇员 ID 号搜索雇员信息的查询的性能。另外,可对
LastName、FirstName、MiddleName
列创建聚集索引,因为经常以这种方式分组和查询雇员记录,而且这些列的组合还可提供高区分度。
按顺序被访问
例如,产品 ID 唯一地标识 AdventureWorks2008R2 数据库的
Proction.Proct 表中的产品。在其中指定顺序搜索的查询(如 WHERE ProctID BETWEEN 980
and 999)将从 ProctID 的聚集索引受益。这是因为行将按该键列的排序顺序存储。
由于保证了列在表中是唯一的,所以定义为 IDENTITY。
经常用于对表中检索到的数据进行排序。
按该列对表进行聚集(即物理排序)是一个好方法,它可以在每次查询该列时节省排序操作的成本。
聚集索引不适用于具有下列属性的列:
频繁更改的列
这将导致整行移动,因为数据库引擎必须按物理顺序保留行中的数据值。这一点要特别注意,因为在大容量事务处理系统中数据通常是可变的。
宽键
宽键是若干列或若干大型列的组合。所有非聚集索引将聚集索引中的键值用作查找键。为同一表定义的任何非聚集索引都将增大许多,这是因为非聚集索引项包含聚集键,同时也包含为此非聚集索引定义的键列。
索引选项
创建聚集索引时,可指定若干索引选项。因为聚集索引通常都很大,所以应特别注意下列选项:
SORT_IN_TEMPDB
DROP_EXISTING
FILLFACTOR
ONLINE
非聚集索引包含索引键值和指向表数据存储位置的行定位器。有关非聚集索引体系结构的详细信息,请参阅非聚集索引结构。
可以对表或索引视图创建多个非聚集索引。通常,设计非聚集索引是为改善经常使用的、没有建立聚集索引的查询的性能。
与使用书中索引的方式相似,查询优化器在搜索数据值时,先搜索非聚集索引以找到数据值在表中的位置,然后直接从该位置检索数据。这使非聚集索引成为完全匹配查询的最佳选择,因为索引包含说明查询所搜索的数据值在表中的精确位置的项。例如,为了从
Person.Person 表中查询具有特定姓氏的人员,查询优化器可能使用非聚集索引
IX_Person_LastName_FirstName_MiddleName;它以 LastName 作为自己的一个键列。查询优化器能快速找出索引中与指定
LastName
匹配的所有项。每个索引项都指向表或聚集索引中准确的页和行,其中可以找到相应的数据。在查询优化器在索引中找到所有项之后,它可以直接转到准确的页和行进行数据检索。
数据库注意事项
设计非聚集索引时需要注意数据库的特征。
更新要求较低但包含大量数据的数据库或表可以从许多非聚集索引中获益从而改善查询性能。与全表非聚集索引相比,考虑为定义完善的数据子集创建筛选索引可以提高查询性能、降低索引存储开销并减少索引维护开销。
决策支持系统应用程序和主要包含只读数据的数据库可以从许多非聚集索引中获益。查询优化器具有更多可供选择的索引用来确定最快的访问方法,并且数据库的低更新特征意味着索引维护不会降低性能。
联机事务处理应用程序和包含大量更新表的数据库应避免使用过多的索引。此外,索引应该是窄的,即列越少越好。
一个表如果建有大量索引会影响
INSERT、UPDATE、DELETE 和 MERGE
语句的性能,因为当表中的数据更改时,所有索引都须进行适当的调整。
查询注意事项
在创建非聚集索引之前,应先了解访问数据的方式。考虑对具有以下属性的查询使用非聚集索引:
使用 JOIN 或 GROUP BY
子句。
应为联接和分组操作中所涉及的列创建多个非聚集索引,为任何外键列创建一个聚集索引。
不返回大型结果集的查询。
创建筛选索引以覆盖从大型表中返回定义完善的行子集的查询。
包含经常包含在查询的搜索条件(例如返回完全匹配的 WHERE 子句)中的列。
列注意事项
考虑具有以下一个或多个属性的列:
覆盖查询。
当索引包含查询中的所有列时,性能可以提升。查询优化器可以找到索引内的所有列值;不会访问表或聚集索引数据,这样就减少了磁盘
I/O 操作。使用具有包含列的索引来添加覆盖列,而不是创建宽索引键。有关详细信息,请参阅
具有包含列的索引
。
如果表有聚集索引,则该聚集索引中定义的列将自动追加到表上每个非聚集索引的末端。这可以生成覆盖查询,而不用在非聚集索引定义中指定聚集索引列。例如,如果一个表在
C 列上有聚集索引,则 B 和 A 列的非聚集索引将具有其自己的键值列 B、A 和 C。
大量非重复值,如姓氏和名字的组合(前提是聚集索引被用于其他列)。
如果只有很少的非重复值,例如仅有 1 和
0,则大多数查询将不使用索引,因为此时表扫描通常更有效。对于这种类型的数据,应考虑对仅出现在少数行中的非重复值创建筛选索引。例如,如果大部分值都是
0,则查询优化器可以对包含 1 的数据行使用筛选查询。
索引选项
在创建非聚集索引时,可以指定若干索引选项。要尤其注意以下选项:
FILLFACTOR
ONLINE
⑺ sql 索引用多了会越来越卡吗
1. 执行计划中明明有使用到索引,为什么执行还是这么慢?
2. 执行计划中显示扫描行数为 644,为什么 slow log 中显示 100 多万行?
a. 我们先看执行计划,选择的索引 “INDX_BIOM_ELOCK_TASK3(TASK_ID)”。结合 sql 来看,因为有 "ORDER BY TASK_ID DESC" 子句,排序通常很慢,如果使用了文件排序性能会更差,优化器选择这个索引避免了排序。
那为什么不选 possible_keys:INDX_BIOM_ELOCK_TASK 呢?原因也很简单,TASK_DATE 字段区分度太低了,走这个索引需要扫描的行数很大,而且还要进行额外的排序,优化器综合判断代价更大,所以就不选这个索引了。不过如果我们强制选择这个索引(用 force index 语法),会看到 SQL 执行速度更快少于 10s,那是因为优化器基于代价的原则并不等价于执行速度的快慢;
b. 再看执行计划中的 type:index,"index" 代表 “全索引扫描”,其实和全表扫描差不多,只是扫描的时候是按照索引次序进行而不是行,主要优点就是避免了排序,但是开销仍然非常大。
Extra:Using where 也意味着扫描完索引后还需要回表进行筛选。一般来说,得保证 type 至少达到 range 级别,最好能达到 ref。
在第 2 点中提到的“慢日志记录Rows_examined: 1161559,看起来是全表扫描”,这里更正为“全索引扫描”,扫描行数确实等于表的行数;
c. 关于执行计划中:“rows:644”,其实这个只是估算值,并不准确,我们分析慢 SQL 时判断准确的扫描行数应该以 slow log 中的 Rows_examined 为准。
4. 优化建议:添加组合索引 IDX_REL_DEVID_TASK_ID(REL_DEVID,TASK_ID)
优化过程:
TASK_DATE 字段存在索引,但是选择度很低,优化器不会走这个索引,建议后续可以删除这个索引:
select count(*),count(distinct TASK_DATE) from T_BIOMA_ELOCK_TASK;+------------+---------------------------+| count(*) | count(distinct TASK_DATE) |+------------+---------------------------+| 1161559 | 223 |+------------+---------------------------+
在这个 sql 中 REL_DEVID 字段从命名上看选择度较高,通过下面 sql 来检验确实如此:
select count(*),count(distinct REL_DEVID) from T_BIOMA_ELOCK_TASK;+----------+---------------------------+| count(*) | count(distinct REL_DEVID) |+----------+---------------------------+| 1161559 | 62235 |+----------+---------------------------+
由于有排序,所以得把 task_id 也加入到新建的索引中,REL_DEVID,task_id 组合选择度 100%:
select count(*),count(distinct REL_DEVID,task_id) from T_BIOMA_ELOCK_TASK;+----------+-----------------------------------+| count(*) | count(distinct REL_DEVID,task_id) |+----------+-----------------------------------+| 1161559 | 1161559 |+----------+-----------------------------------+
在测试环境添加 REL_DEVID,TASK_ID 组合索引,测试 sql 性能:alter table T_BIOMA_ELOCK_TASK add index idx_REL_DEVID_TASK_ID(REL_DEVID,TASK_ID);
添加索引后执行计划:
这里还要注意一点“隐式转换”:REL_DEVID 字段数据类型为 varchar,需要在 sql 中加引号:AND T.REL_DEVID = 000000025xxx >> AND T.REL_DEVID = '000000025xxx'
执行时间从 10s+ 降到 毫秒级别:
1 row in set (0.00 sec)
结论
一个典型的 order by 查询的优化,添加更合适的索引可以避免性能问题:执行计划使用索引并不意味着就能执行快。
⑻ SQL聚集索引和非聚集索引的区别
聚集索引:也称 Clustered Index。是指关系表记录的物理顺序与索引的逻辑顺序相同。由于一张表只能按照一种物理顺序存放,一张表最多也只能存在一个聚集索引。与非聚集索引相比,聚集索引有着更快的检索速度。
MySQL 里只有 INNODB 表支持聚集索引,INNODB 表数据本身就是聚集索引,也就是常说 IOT,索引组织表。非叶子节点按照主键顺序存放,叶子节点存放主键以及对应的行记录。所以对 INNODB 表进行全表顺序扫描会非常快。
非聚集索引:也叫 Secondary Index。指的是非叶子节点按照索引的键值顺序存放,叶子节点存放索引键值以及对应的主键键值。MySQL 里除了 INNODB 表主键外,其他的都是二级索引。MYISAM,memory 等引擎的表索引都是非聚集索引。简单点说,就是索引与行数据分开存储。一张表可以有多个二级索引。
关键词:爱可生、开源数据库、数据监测、数据库运维
⑼ sql使用复合索引要注意什么
sql复合索引一定要注意搜索条件的设置。
还有就是看你用的是什么数据库,mysql和oracle,sqlserver都有各自的设定,需要自己去学