SQL索引-初学心得和基本使用

       对于一个MySQL的初学者来说,数据库的索引和优化可能并没有太大的感觉吧,因为我们并没有面对过大数据的搜索的工作,在小的数据中,由于咱电脑速度还是比较快的,所以也没什么感觉。我刚刚学数据库的时候,一直以为数据库是很智能的,我们加入、删除和查询的时候都是用很优的算法进行,但是今天我学习了数据库索引之后才发现,原来当我们对一个表如果不是用主键进行查询的时候,数据库是进行逐行比对的方式进行搜索,这应该是最慢最无语的方法了,所以我们需要创建合适的索引帮助我们实现数据库的查询。 

       首先,笔者也是个二逼孩子。。。开始学的时候,以为有了primary key我们就能很快的查询了,也觉得索引应该是基于primary key的。这种脑残的想法不会只有我一个人有吧,所以开头我们就先谈下索引和primary key的区别吧。 我们需要知道主键是索引,但索引不一定是主键。并且主键具有唯一性,而只有唯一性索引才具有唯一性,主键的值不能为空,不能重复,但是索引可以在我们程序中动态创建删除。在作用方面:索引只是加快查询和排序等操作的速度,但是primary key则是用于保证数据的完整性,同时也避免编写一些触发器。 

       好了,下面进入正题哈: 

       首先,我们需要知道索引是什么,索引是一种特殊的文件,它们包含着对数据表里所有记录的引用指针。就好比我们的数据是一本书,而索引是书的目录,在没有索引的情况下,我们在查找内容时需要逐页、逐行得进行搜索、比对,但是,在有了索引后,我们就可以直达我们需要的内容。 

       索引分为聚簇索引和非聚簇索引两种,聚簇索引是按照数据存放的物理位置为顺序的,而非聚簇索引就不一样了;聚簇索引能提高多行检索的速度,而非聚簇索引对于单行的检索很快。 在这里,笔者就在思考一个问题了,聚簇索引是要求文件的存放是有序的,而非聚簇索引则是无序的,这样的话,在使用索引时我们就有很大的限制了,那么我们应该怎样解决这个问题呢,有待讨论哈。 索引是可以动态生成的,在我们程序时候的时候生成一个需要的索引,在不需要的时候则进行删除,但是,当我们数据规模很大的时候,生成索引是一个极消耗资源的事情,但是呢,索引又是很庞大的,很占用空间,所以我们需要找到运算效率和存储空间的一个平衡点。合理利用索引才能提高查询效率,如果将很多时间用在创建索引上就非常不值得了。 

       这里我们使用的MySQL,在MySQL中的索引使用的都是B-TREE,这应该是最平衡的一种结构了,当然有的使用的HASH索引,应该说各有利弊,大家可以查一下实现的方式学习一下,也有助于自己在今后在想要实现不同功能的时候灵活选择索引的种类。

       索引也是有很大坏处的,由于需要大大提高查询的速度,所以需要创建大量的指针和表,在进行INSERT、UPDATE、DELETE等修改操作时,由于索引的存在,在更新数据的同时,也需要更新索引的文件,所以,滥用索引反而会大大降低数据库的效率。 上面已经说过了,索引分为聚簇索引和非聚簇两类,那么,对索引类型的选择也就是一个问题。 聚簇索引和非聚簇索引的区别google看一看哈! 

       选择标准可以参考下表(网上找的):《SQL索引-初学心得和基本使用》

下面,粗略介绍下索引的类型和使用吧,详细的大家可以看MySQL的document,但是比较繁琐难懂就是了。

   1. 普通索引

   这是最基本的索引,它没有任何限制,我们应该很少用到,但是还是要熟练掌握的。

   –直接创建索引

   CREATE INDEX indexName ON tableName(columnName)

   –修改表结构的方式添加索引

   ALTER TABLE tabelName ADD INDEX indexName(columnName)

   –创建表的时候同时创建索引

   CREATE TABLE tableName (

   INDEX indexName (title(length))

   )   

   2. 唯一索引

   primary key 就是一个唯一索引,与普通索引类似,不同的就是:索引列的值必须唯一,但允许有空。如果是组合索引,则列值的组合必须唯一。

   –创建唯一索引

   CREATE UNIQUE INDEX indexName ON tableName(column)

   –修改表结构

   ALTER TABLE tableName ADD UNIQUE indexName (columnName)

   –创建表的时候直接指定

   CREATE TABLE tableName (

   UNIQUE indexName (title(length))

   );

    3. 全文索引(FULLTEXT)

    MySQL从3.23.23版开始支持全文索引和全文检索,FULLTEXT索引仅可用于 MyISAM 表;他们可以从CHAR、VARCHAR或TEXT列中作为CREATE TABLE语句的一部分被创建,或是随后使用ALTER TABLE 或CREATE INDEX被添加。

    对于较大的数据集,将你的资料输入一个没有FULLTEXT索引的表中,然后创建索引,其速度比把资料输入现有FULLTEXT索引的速度更为快。当然了,由于全文索引的特殊性,当数据量很大的时候,我们进行全文索引的创建极度消耗运算资源,所以不建议在程序中动态得创建和删除。同时,建议如果使用全文搜索,应该在建表的时候就进行建立索引。

–创建表的适合添加全文索引

CREATE TABLE tableName (

FULLTEXT (content)

);

–修改表结构添加全文索引

ALTER TABLE article ADD FULLTEXT index_content(content)

–直接创建索引

CREATE FULLTEXT INDEX index_content ON article(content)

    4. 单列索引、多列索引

    多个单列索引与单个多列索引的查询效果不同,因为执行查询时,MySQL只能使用一个索引,会从多个索引中选择一个限制最为严格的索引。对于新学者和小网站来说,多列索引应该是最多用的,也是最容易掌握的索引方式。

    大家可以搜一下,有许多大牛都进行了验证,多列搜索是总体优于单列搜索的,这里就不进行证明了。

    5. 组合索引(最左前缀)

    平时用的SQL查询语句一般都有比较多的限制条件,所以为了进一步榨取MySQL的效率,就要考虑建立组合索引。例如一个组合索引:ALTER TABLE tableName ADD INDEX indexName(a(50),b(10))。建立这样的组合索引,其实是相当于分别建立了下面两组组合索引:

–a,b

–a

   说一点点学习心得:学习SQL是一个非常烦索的过程,我们不应该仅仅局限于会使用,善于使用。正所谓磨刀不误砍柴功,在学习过程中应该注重一下基础的数学理论,不要急于做项目、做工程。

   附上刚刚写的DB作业的数据库代码吧。。。好渣渣,给新学者们一个参考:

CREATE DATABASE IF NOT EXISTS DBJob character set UTF8;
USE DBJob;

CREATE TABLE student(
    sid VARCHAR(45) NOT NULL,
    name VARCHAR(45) NOT NULL,
    university VARCHAR(45) NOT NULL,
    email VARCHAR(45) NULL,
    phone VARCHAR(45) NOT NULL,
    password VARCHAR(45) NOT NULL,
    PRIMARY KEY (sid));

alter table student add index FIND_BY_NAME(name);
alter table student add index MULTI_FIND_S(sid,name);

CREATE TABLE enterprise(
    eid VARCHAR(45) NOT NULL,
    ename VARCHAR(45) NOT NULL,
    phone VARCHAR(45) NOT NULL,
    email VARCHAR(45) NULL,
    password VARCHAR(45) NOT NULL,
    detail_information VARCHAR(200) NULL,
    PRIMARY KEY (eid));

alter table enterprise add index FIND_BY_ENAME(ename);
alter table enterprise add index MULTI_FIND_E(eid,ename);

CREATE TABLE job(
    jid INT NOT NULL,
    eid VARCHAR(45) NOT NULL,
    workplace VARCHAR(45) NULL,
    category VARCHAR(45) NULL,
    start_time DATETIME NOT NULL,
    end_time DATETIME NOT NULL,
    payment VARCHAR(45) NULL,
    paytype char(1) NULL,
    rec_num INT NULL,
    detail VARCHAR(45) NULL,
    PRIMARY KEY (jid,eid),
    CONSTRAINT eid
        FOREIGN KEY (eid)
        REFERENCES enterprise (eid)
        ON DELETE NO ACTION
        ON UPDATE NO ACTION);

alter table job add index FIND_BY_EID(eid);
alter table job add index FIND_BY_PAY(payment);
alter table job add index FIND_BY_TIME(start_time,end_time);

CREATE TABLE job_wanted(
    sid VARCHAR(45) NOT NULL,
    jid INT NOT NULL,
    PRIMARY KEY (jid, sid),
	FOREIGN KEY (sid)
	REFERENCES student (sid),
	FOREIGN KEY (jid)
	REFERENCES job (jid)
        ON DELETE NO action
        ON UPDATE NO action);

    原文作者:mysql索引优化
    原文地址: https://my.oschina.net/VicoAndMe/blog/270840
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞