提高数据库查询效率的方法:创建多字段索引 (数据库创建多字段索引)

在当今信息化时代,数据库已经成为各种企业、机构和组织中必不可少的数据管理工具,通过对各类数据进行存储、查询、更新等操作,为组织决策和业务运营提供重要的支撑。然而,如果不对数据库的性能进行优化,长时间使用容易出现查询缓慢甚至崩溃的问题,给用户和业务带来相当大的困扰和损失。为了解决这类问题,本文将探讨一种。

什么是多字段索引?

一般来说,当我们需要对数据库中的一张表进行复杂查询时,比如需要查询多个字段的值满足特定条件的记录,如果使用单字段索引,则需要针对每个字段各创建一个索引,这样在查询时需要对所有索引进行遍历,显然速度很慢。而多字段索引则是指针对多个字段创建一个索引,比如CREATE INDEX idxname ON tablename (field1, field2, ……, fieldn),这样只需要对一个索引进行遍历,提高了查询效率。

多字段索引的使用场景

在什么情况下需要使用多字段索引呢?以下是几个可能的场景:

1. 复合查询:如果查询需要满足多个条件,比如SELECT * FROM employees WHERE department=’sales’ AND salary>5000 AND age

2. 顺序查询:如果查询需要按照某个字段的顺序进行排序或分组,比如SELECT * FROM employees ORDER BY department, salary,则可以针对department和salary这两个字段创建一个多字段索引,这样可以避免对两个字段分别进行排序或分组,提高效率。

3. 子查询:如果查询涉及到嵌套子查询,比如SELECT salesperson, department, sales_amount FROM sales WHERE sales_amount > (SELECT AVG(sales_amount) FROM sales),则可以针对sales_amount这个字段创建一个索引,同时salesperson和department也可以加入到多字段索引中,这样可以提高子查询和连接操作的效率。

4. 类型转换:如果查询涉及到对字段类型进行转换,比如SELECT * FROM orders WHERE DATE_FORMAT(order_date,’%Y-%m-%d’)=’2023-05-01’,则可以创建一个多字段索引,包括order_date和DATE_FORMAT(order_date,’%Y-%m-%d’),这样可以避免对每个记录进行类型转换。

需要注意的是,在创建多字段索引时,需要根据实际使用场景权衡各个字段的顺序,确定多字段索引的顺序,这样可以避免不必要的索引遍历,影响查询效率。

多字段索引的优点和缺点

与单字段索引相比,多字段索引具有以下优点:

1. 提高查询效率:多字段索引可以避免对多个单字段索引进行遍历,从而提高查询效率。

2. 减少索引数量:通过使用多字段索引可以减少索引的数量,避免不必要的维护和资源占用。

3. 提高空间利用率:多字段索引可以将多个索引合并到一起,提高空间利用率。

不过,多字段索引也有一些缺点:

1. 创建和维护成本高:与单字段索引相比,多字段索引创建和维护成本更高,需要耗费更多的资源和时间。

2. 可能增加查询复杂度:如果多字段索引的顺序不当,可能会增加查询复杂度,降低查询效率。

3. 可能导致磁盘占用增加:多字段索引占用的磁盘空间可能更大,特别是如果需要对多个字段进行数据类型转换时。

如何创建多字段索引

创建多字段索引需要注意以下几点:

1. 在确定需要创建多字段索引时,需要先选择需要建立索引的字段,尽量避免选择过多的字段。

2. 根据实际使用场景选择合适的字段顺序,避免不必要的索引遍历。

3. 在创建多字段索引时需要考虑磁盘空间和资源占用的成本,并进行必要的优化和调整。

4. 注意维护索引的一致性和可用性,定期进行索引优化和重建。

使用多字段索引可以大大提高数据库查询效率,从而促进业务运营的高效发展。然而,需要注意的是,在实际使用过程中,需要综合考虑多个因素,包括数据库的大小、访问频率、查询条件等,选择合适的索引类型和数量。只有在实际场景中合理使用多字段索引,才能发挥更大的优势。

相关问题拓展阅读:

MySQL最多可建立多少索引和索引的限制

MySQL

索引

类型包括:

一、普通索引

这是最基本的索引,它没有任何限制。有以下几种创建方式:

1.创建索引

代码如下:

CREATE INDEX indexName ON mytable(username(length));

如果是CHAR,VARCHAR类型,length可以小于字段实际长度;如果是BLOB和TEXT类型,必须指定 length,下同。

2.修改表结构

代码如下:

ALTER mytable ADD INDEX ON (username(length)) — 创建表的时候直接指定。

CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, INDEX (username(length)) );

— 删除索引的语法:

DROP INDEX ON mytable;

二、唯一索引

它与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必运卖须唯一。它有以下几种创建方式:

代码如下:

CREATE UNIQUE INDEX indexName ON mytable(username(length))

— 修旁清逗改表结构

ALTER mytable ADD UNIQUE ON (username(length))

— 创建表的时候直接指定

CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, UNIQUE (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的效率,就要考虑建立组合索引。

二:使用索引的注意事项

使用索引时,有以下一些技巧和注意事项:

1.索引不会包含有NULL值的列

只要列中包含有NULL值都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此复合索引就是无效的。所以我们在

数据库设计

时不要让字段的默认值为NULL。

2.使用短索引

对串列进行索引,如果可能应该指定一个前缀长度。例如,如果有一个CHAR(255)的列,如正好果在前10个或20个字符内,多数值是惟一的,那么就不要对整个列进行索引。短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作。

3.索引列排序

MySQL查询只使用一个索引,因此如果where子句中已经使用了索引的话,那么

order by

中的列是不会使用索引的。因此数据库默认排序可以符合要求的情况下不要使用排序操作;尽量不要包含多个列的排序,如果需要更好给这些列创建复合索引。

4.like语句操作

一般情况下不鼓励使用like操作,如果非使用不可,如何使用也是一个问题。like “%aaa%” 不会使用索引而like “aaa%”可以使用索引。

5.不要在列上进行运算

select * from users where YEAR(adddate)操作。

三:sql优化原则

常见的简化规则如下:

1.不要有超过5个以上的表连接(JOIN)

2.考虑使用临时表或表变量存放中间结果。

3.少用子查询

4.视图嵌套不要过深,一般视图嵌套不要超过2个为宜。

5.连接的表越多,其编译的时间和连接的开销也越大,性能越不好控制。

6.更好是把连接拆开成较小的几个部分逐个顺序执行。

7.优先执行那些能够大量减少结果的连接。

8.拆分的好处不仅仅是减少SQL Server优化的时间,更使得SQL语句能够以你可以预测的方式和顺序执行。

如果一定需要连接很多表才能得到数据,那么很可能意味着设计上的缺陷。

在满足语句需求的情况下,尽盯巧量少的访问资源是数据库设计的重要原则,这和执行的 SQL 有直接的关系,索引问题又是 SQL 问题中出现频率更高的,常见的索引问题包括:无索引(失效)、隐式转换。

1. SQL 执行流程看一个问题,在下面这个表 T 中,如果我要执行 select * from T where k between 3 and 5; 需要执行几次树的搜索操作,会扫描多少行?mysql> create table T (    -> ID int primary key,    -> k int NOT NULL DEFAULT 0,    -> s varchar(16) NOT NULL DEFAULT ”,    -> index k(k))    -> engine=InnoDB;mysql> insert into T values(100,1, ‘aa’),(200,2,’bb’),\      (300,3,’或慧cc’),(500,5,’ee’),(600,6,’ff’),(700,7,’gg’);

这分别是 ID 字段索引树、k 字段索引树。 

这条 SQL 语句的执行流程:

1. 在 k 索引树上找到 k=3,获得 ID=3002. 回表到 ID 索引树查找 ID=300 的记录,对应 R33. 在 k 索引树找到下一个值 k=5,ID=5004. 再回到 ID 索引树找到对应 ID=500 的 R4

5. 在 k 索引树去下一个值 k=6,不符合条件,循环结束

这个过程读取了 k 索引树的三条记录,回表了两次。因为查询结果所需要的数据只在主键索引上有,所以必须得回表。所以,我们该如何通过优化索引,来避免回表呢?

2. 常见索引优化2.1 覆盖索引覆盖索引,换言之就是索引要覆盖我们的查询请求,无需回表。

如果执行的语句是 select ID from T wherek between 3 and 5;,这样的话因为 ID 的值在 k 索引树上,就不需要回表了。

覆盖索引可以减少树的搜索次数,显著提升查询性能,是常用的性能优化手衫则答段。

但是,维护索引是有代价的,所以在建立冗余索引来支持覆盖索引时要权衡利弊。

2.2 最左前缀原则

B+ 树的数据项是复合的数据结构,比如 (name,sex,age) 的时候,B+ 树是按照从左到右的顺序来建立搜索树的,当 (张三,F,26) 这样的数据来检索的时候,B+ 树会优先比较 name 来确定下一步的检索方向,如果 name 相同再依次比较 sex 和 age,最后得到检索的数据。

# 有这样一个表 P

mysql> create table P (id int primary key, name varchar(10) not null, sex varchar(1), age int, index tl(name,sex,age)) engine=IInnoDB;

mysql> insert into P values(1,’张三’,’F’,26),(2,’张三’,’M’,27),(3,’李四’,’F’,28),(4,’乌兹’,’F’,22),(5,’张三’,’M’,21),(6,’王五’,’M’,28);

# 下面的语句结果相同

mysql> select * from P where name=’张三’ and sex=’F’;     ## A1

mysql> select * from P where sex=’F’ and age=26;## A2

# explain 看一下

mysql> explain select * from P where name=’张三’ and sex=’F’;

+—-++++——+-+——+++——+++

| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref| rows | filtered | Extra|

+—-++++——+-+——+++——+++

|  1 | SIMPLE      | P     | NULL| ref  | tl| tl   || const,const |    1 |   100.00 | Using index |

+—-++++——+-+——+++——+++

mysql> explain select * from P where sex=’F’ and age=26;

+—-+++++-+——++——+——+++

| id | select_type | table | partitions | type  | possible_keys | key  | key_len | ref  | rows | filtered | Extra      |

+—-+++++-+——++——+——+++

|  1 | SIMPLE      | P     | NULL| index | NULL| tl   || NULL |    6 |    16.67 | Using where; Using index |

+—-+++++-+——++——+——+++

可以清楚的看到,A1 使用 tl 索引,A2 进行了全表扫描,虽然 A2 的两个条件都在 tl 索引中出现,但是没有使用到 name 列,不符合最左前缀原则,无法使用索引。所以在建立联合索引的时候,如何安排索引内的字段排序是关键。评估标准是索引的复用能力,因为支持最左前缀,所以当建立(a,b)这个联合索引之后,就不需要给 a 单独建立索引。原则上,如果通过调整顺序,可以少维护一个索引,那么这个顺序往往就是需要优先考虑采用的。上面这个例子中,如果查询条件里只有 b,就是没法利用(a,b)这个联合索引的,这时候就不得不维护另一个索引,也就是说要同时维护(a,b)、(b)两个索引。这样的话,就需要考虑空间占用了,比如,name 和 age 的联合索引,name 字段比 age 字段占用空间大,所以创建(name,age)联合索引和(age)索引占用空间是要小于(age,name)、(name)索引的。

2.3 索引下推

以人员表的联合索引(name, age)为例。如果现在有一个需求:检索出表中“名字之一个字是张,而且年龄是26岁的所有男性”。那么,SQL 语句是这么写的mysql> select * from tuser where name like ‘张%’ and age=26 and sex=M;

通过最左前缀索引规则,会找到 ID1,然后需要判断其他条件是否满足在 MySQL 5.6 之前,只能从 ID1 开始一个个回表。到主键索引上找出数据行,再对比字段值。而 MySQL 5.6 引入的索引下推优化(index condition pushdown),可以在索引遍历过程中,对索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数。这样,减少了回表次数和之后再次过滤的工作量,明显提高检索速度。

2.4 隐式类型转化

隐式类型转化主要原因是,表结构中指定的数据类型与传入的数据类型不同,导致索引无法使用。所以有两种方案:

修改表结构,修改字段数据类型。

修改应用,将应用中传入的字符类型改为与表结构相同类型。

3. 为什么会选错索引3.1 优化器选择索引是优化器的工作,其目的是找到一个更优的执行方案,用最小的代价去执行语句。在数据库中,扫描行数是影响执行代价的因素之一。扫描的行数越少,意味着访问磁盘数据的次数越少,消耗的 CPU 资源越少。当然,扫描行数并不是唯一的判断标准,优化器还会结合是否使用临时表、是否排序等因素进行综合判断。

3.2 扫描行数

MySQL 在真正开始执行语句之前,并不能精确的知道满足这个条件的记录有多少条,只能通过索引的区分度来判断。显然,一个索引上不同的值越多,索引的区分度就越好,而一个索引上不同值的个数我们称为“基数”,也就是说,这个基数越大,索引的区分度越好。# 通过 show index 方法,查看索引的基数mysql> show index from t;++++++++++——+++-+| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |++++++++++——+++-+| t     || PRIMARY  || id| A||     NULL | NULL   |      | REE      || || t     || a|| a| A||     NULL | NULL   | YES  | REE      || || t     || b|| b| A||     NULL | NULL   | YES  | REE      || |++++++++++——+++-+

MySQL 使用采样统计方法来估算基数:采样统计的时候,InnoDB 默认会选择 N 个数据页,统计这些页面上的不同值,得到一个平均值,然后乘以这个索引的页面数,就得到了这个索引的基数。而数据表是会持续更新的,索引统计信息也不会固定不变。所以,当变更的数据行数超过 1/M 的时候,会自动触发重新做一次索引统计。

在 MySQL 中,有两种存储索引统计的方式,可以通过设置参数 innodb_stats_persistent 的值来选择:

on 表示统计信息会持久化存储。默认 N = 20,M = 10。

off 表示统计信息只存储在内存中。默认 N = 8,M = 16。

由于是采样统计,所以不管 N 是 20 还是 8,这个基数都很容易不准确。所以,冤有头债有主,MySQL 选错索引,还得归咎到没能准确地判断出扫描行数。

可以用 yze table 来重新统计索引信息,进行修正。

ANAZE TABLE tbl_name …

在Oracle中合理创建数据库的索引

在Oracle数据库中 创建索引虽然比较简单 但是要合理的创建索引则比较困慧塌难了 笔者认为 在创建索引时要做到三个适当 即在适当的表上 适当的列上创建适当数量的索引 虽然这可以通过一句话来概括优化的索引的基本准则 但是要做到这一点的话 需要数据库管理员做出很大的努力 具体的来说 要做到这个三个适当有如下几个要求

  

一 根据表的大小来创建索引

  虽然给表创建索引 可以提高查询的效率 但是数据库管理员需要注意的是 索引也需要一定的开销的 为此并不是说给所有的表都创建索引 那么就可以提高数据库的性能 这个认识是错误的 恰恰相反 如果不管三七二十一 给所有的表都创建了索引 那么其反而会给数据库的性能造成负面的影响 因为此时滥用索引的开销可能已经远远大于由此带来的性能方面的收益 所以笔者认为 数据库管理员首先需要做到 为合适的表来建立索引 而不是为所有的表建立索引

  一般来说 不需要为比较小的表创建索引 如在一个ERP系统的数据库中 department表用来存储企业部门的信息 一般企业的部分也就十几个 最多不会超过一百个 这 条记录对于人来说 可能算是比较多了 但是对于计算机来说 这给他塞塞牙缝都还不够 所以 对类似的小表没有必要建立索引 因为即使建立了索引 其性能也不会得到很大的改善 相反索引建立的开销 如维护成本等等 要比这个要大 也就是说 付出的要比得到的多 显然违反常理

  另外 就是对于超大的表 也不一定要建立索引 有些表虽然比较大 记录数量非常的多 但是此时为这个表建立索引并一定的合适 如系统中有一张表 其主要用来保存数据库中的一些变更信息 往往这些信息只给数据库管理员使用 此时为这张表建立索引的话 反而不合适 因为这张表很少用到 只有在出问题的时候才需要查看 其次其即使查看 需要查询的纪录也不会很多 可能就是最近一周的更新记录等等 对于对于一些超大的表 建立索引有时候往往不能够达到预计的效果 而且在打表上建立索引 其索引的开销要比普通的表大的多 那么到底是否给大表建立索引呢?笔者认为 主要是看两个方面的内容 首前中圆先是需要关注一下 在这张大表中经常需要查询的记录数量 一般来说 如果经常需要查询的数据不超过 %到 %的话 那就没有必要为其建立索引的必要 因为此时建立索引的开销可能要比性能的改善大的多 这个比例只是一个经验的数据 如果数据库管理员需要得出一个比较精确的结论 那么就需要进行测试分析 即数据库管理员需要测试一下全表扫描的时间 看看其是否比建立索引后的查询时间要长或者短 如果是长的话 则说明有建立索引的必要 但是如果没有的话 则说明还是全表扫描速度来的快 此时也就没有必要建立索引了

  总之 在考虑是否该为表建立索引时 一般来说小表没有建立索引的必要 而对于打表的话 则需要进行实际情况实际分析 简单一点的 可以根据大致的比率来确定 如果要精确一点的 则可以进行全表扫描性能分析 以判断建立索引后是否真的如预期那样改善了数据库性能

  

二 根据列的特征来创建索引

  列的特点不同 索引创建的效果也不同 数据库管理员需要了解为哪些列创建索引可以起到事倍功半的效果 同时也需要了解为哪些列创建索引反而起到的是事倍功半的效果 这有利于他们了解到底给为怎么样的字段建立索引

  根据笔者的经验 往往为如下特征的列创建索引能够起到比较明显的效果 如对于一些重复内容比较少的列 特别是对于那些定义了唯一约束的列 在这些列上建立索引 往往可以起到非常不错的效果 如对于一些null值的列与非Null值的列培敏混合情况下 如果用户需要经常查询所有的非Null值记录的列 则更好为其设置索引 如果经常需要多表连接查询 在用与连接的列上设置索引可以达到事半功倍的效果

  可见 索引设置的是否恰当 不仅跟数据库设计架构有关 而且还跟企业的经济业务相关 为此 对于一些套装软件 虽然一开始数据库管理员已经做了索引的优化工作 但是随着后来经济数据的增加 这个索引的效果会越来越打折扣 这主要是因为记录的表化影响到了索引优化的效果 所以笔者建议各位数据库管理员 即使采用的是大牌软件公司的套装软件 也需要隔一段时间 如一年 对数据库的索引进行优化 该去掉的去掉 该调整的调整 以提高数据库的性能

  如在数据库中有一张表是用来保存用户信息的 其中有个字段身份证号码 这是一个唯一的字段 在数据库设计时 给这个字段创建了索引 但是当这个数据库投入使用之后 用户不怎么输入用户的身份证号码 而且平时也基本不按这个号码来进行查询 当记录月来月多时 这个身份证号码上的索引字段不但不能够改善数据库的查询性能 反而成了鸡肋 对于这些有很多NULL值的列 而且不会经常查询所有的非NULL值记录的列 数据库管理员要下决心 即使清除这些列上的索引

  所以说索引的优化与调整是一个动态的过程 并不是说数据库设计好之后就不需要经过调整 数据库管理员往往需要根据记录的变化情况 来进行适当的变更 以提高索引的效果

  

三 在一个表上创建多少索引合适?

  虽然说 在表上创建索引的数量没有限制 但是决不是越多越好 也就是说 在创建索引这项事情上 + 〉 往往不成立 有时候 创建索引越多 其可能会得到适得其反的效果 那么在一个表上 到底给创建多少索引合适呢?这个没有一个明确的标准 而是需要数据库管理员根据实际的用途以及数据库中记录的情况 来进行判断

  通常来说 表的索引越多 其查询的速度也就越快 但是 表的更新速度则会降低 这主要是因为表的更新(如往表中插入一条记录)速度 反而随着索引的增加而增加 这主要是因为 在更新记录的同时需要更新相关的索引信息 为此 到底在表中创建多少索引合适 就需要在这个更新速度与查询速度之间取得一个均衡点 如对于一些数据仓库或者决策型数据库系统 其主要用来进行查询 相关的记录往往是在数据库初始化的时候倒入 此时 设置的索引多一点 可以提高数据库的查询性能 同时因为记录不怎么更新 所以索引比较多的情况下 也不会影响到更新的速度 即使在起初的时候需要导入大量的数据 此时也可以先将索引禁用掉 等到数据导入完毕后 再启用索引 可以通过这种方式来减少索引对数据更新的影响 相反 如果那些表中经常需要更新记录 如一些事务型的应用系统 数据更新操作是家常便饭的事情 此时如果在一张表中建立过多的索引 则会影响到更新的速度 由于更新操作比较频繁 所以对其的负面影响 要比查询效率提升要大的多 此时就需要限制索引的数量 只在一些必要的字段上建立索引

  笔者在平时数据库优化时 往往会根据这些表的用途来为列设置索引 可以查询相关的动态视图 看看对于这张表的操作 是更新操作(包括更新 删除 插入等等)占的比例大 还是查询操作占的比例大 当过多的索引已经影响到更新操作的速度时 则数据库管理员就需要先禁用某些索引 以提高数据库的性能

lishixinzhi/Article/program/Oracle/202311/18407

数据库的索引以及在哪些列上创建索引

选择开始菜单中→程序→【management

sql

server

2023】→【sql

server

management

studio】命令,打开【sql

server

management

studio】窗口,并使用windows或

sql

server身份验证建立连接。

在【对象资源管理器】窗口中展开服务器,然后选择【数据库】节点

右键单击【数据库】节点,从弹出来的快捷菜单中选择【新建数据库】命令。

执行上述操作后,会弹出【新察毕此建数据库】对话框。在对话框、左侧有3个选项,分别是【常规】、【选项】和【文件组】。完成这三个选项中的设置会后,就完成了数据库的创建工作,

在【数据库名称】文本框中数闭输入要新建数据库的名称。例如,这里以“新建的数据库”。

在【所有者】文本框中输入新败迅建数据库的所有者,如sa。根据数据库的使用情况,选择启用或者禁用【使用全文索引】复选框。

在【数据库文件】列表中包括两行,一行是数据库文件,而另一行是日记文件。通过单击下面的【添加】、【删除】按钮添加或删除数据库文件。

切换到【选项页】、在这里可以设置数据库的排序规则、恢复模式、兼容级别和其他属性。

切换到【文件组】页,在这里可以添加或删除文件组。

完成以上操作后,单击【确定】按钮关闭【新建数据库】对话框。至此“新建的数据”数据库创建成功。新建的数据库可以再【对象资源管理器】窗口看到。

数据库创建多字段索引的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于数据库创建多字段索引,提高数据库查询效率的方法:创建多字段索引,MySQL最多可建立多少索引和索引的限制,在Oracle中合理创建数据库的索引,数据库的索引以及在哪些列上创建索引的信息别忘了在本站进行查找喔。


数据运维技术 » 提高数据库查询效率的方法:创建多字段索引 (数据库创建多字段索引)