字段类型选择慷慨是不明智的在相关的表中使用相同的数据类型,因为可能进行join选择标示符:整数通常是最佳选择,尽量避免使用字符串大致决定数据类型(数字,字符串,时间等)选择存储更小的类型,选择更简单的类型(如整数优于字符串),选择mysql内建时间类型而不是字符串,选择整数而不是字符串来保存IP尽量避免使用NULL:任何包含null值的列都将不会被包含在索引中。即使索引有多列这样之情况下,只要这些列中有一列含有null,该列就会从索引中排除。也就是说如果某列存在空值,即使对该列建索引也不会提高性能。确定特定类型varchar(字节数) 变长字符串varchar内容开头用1到2个字节表示实际长度(长度超过255时需要2个字节),因此最大长度不能超过655355.0之后的mysql对其读写都会保留末尾空格插入过量会被截断但是不报错char 定长字符串对其写,会去掉末尾空格比较varchar容易产生碎片,char不会最大长度远大于平均长度的,适用varchar固定长度,或者最大长度很短的,适用于char整数 tinyint (8bit) smallint (16bit) mediumint (24bit) int (32bit) bigint (24bit)signed 和 unsigned 占用空间一致, 后者把最大值大概扩大了一倍整数类型定义宽度( 如 int(10) unsigned )对存储没有影响,只是影响某些交互工具展示实数 TODO数字字符串binary 和 varbinary:保存二进制字符串,他们保存的是字节而不是字符,填充是 而不是空格blob 和 text: 不能索引这些类型的完整长度,也不能为排序使用索引排序时只按照max_sort_length规定的若干字节排序,或者可以自己指定 order by substring(column, length)enum建表时指定该类型: create table table_name (column_name enum(‘a‘, ‘b‘, ‘c‘) not null);该字段将是1到2个字节(所有最多的枚举数是65535),存储的书数字select 出来的字段值将是字符串可以将其转为数字: select column_name + 0 ...内部排序是按照数字(所以定义的时候应该注意顺序),或者显式指定:order by field(column_name, (‘b‘, ‘a‘, ‘c‘))在建表后需要新增枚举种类只能alter table,所有不适合种类不确定的类型优势:节约空间 劣势:join字符串时会较慢(存在转换)日期和时间yeardatedatetime 8字节存储,和时区无关,1001年到9999年,精度为秒timestamp 4字节,和时区相关,表示从1970年1月1日以来的秒数通常应该用timestamp,更节约空间BIT TODOSET TODO索引索引类型:B-Tree索引:除了Archive引擎外都支持Hash索引:Memory引擎,可以在其它B-Tree索引上建立自己的Hash索引:增加一列被索引的列(作为Hash的key),该列允许一定得碰撞,需要一个hash函数(如CRC32),不应该使用强加密函数(如SHA1 MD5等,碰撞低但是费空间,查找速度慢)R-Tree索引:MyISAM支持 #TODOFULLTEXT: MyISAM支持 #TODO高性能索引策略隔离列:列不是表达式的一部分,也不在函数之中EXPLAINid 表示执行顺序id从大到小,id相同从上往下select_type 查询类型SIMPLE:查询中不包含子查询或者UNIONPRIMARY 查询中若包含任何复杂的子部分,最外层查询则被标记为PRIMARYSUBQUERY 在SELECT或WHERE列表中包含了子查询,该子查询被标记为SUBQUERYDEPEDENT SUBQUERY 依赖外部查询的子查询DERIVD 在FROM列表中包含的子查询被标记为DERIVED(衍生)UNION RESULT 从UNION表获取结果的SELECT被标记为UNION RESULTtable 记录查询引用的表TYPE:访问类型,表示MySQL在表中找到所需行的方式从最好到最差:(唯一或非唯一)组合索引的前一部分:select * from t where unique_or_not_unique_combined_index_1 = ‘abc‘非唯一组合或单列索引的全部:select * from t where not_unique_combined_index_1 = ‘abc‘ and not_unique_combined_index_2 = ‘123‘唯一索引的前缀匹配:NULL:MySQL在优化过程中分解语句,执行时甚至不用访问表或索引, 比如id=-1, min(id) max(id)????#TODOselect * from deals where id=-1;select max(id) from deals;system: 表只有一行记录(等于系统表)。这是 const表连接类型的一个特例,下例中子查询是const,主查询是system:select * from ( select * from deals where id=1)t;const: 表中最多只有一行匹配的记录,它在查询一开始的时候就会被读取出来(腾云科技ty300.com)。由于只有一行记录,在余下的优化程序里该行记录的字段值可以被当作是一个恒定值。const表查询起来非常快,因为只要读取一次!const 用于在和 primary key 或unique 索引中有固定值比较的情形select * from tbl_name where primary_key=1;select * from tbl_name where primary_key_part1=1 and primary_key_part2=2;eq_ref:唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。常见于主键或唯一索引扫描。 这是最好的连接类型。它用在索引所有部分都用于做连接并且这个索引是一个primary key 或 unique 类型。eq_ref可以用于在进行"="做比较时检索字段。下列先对user_trades全表扫描(ALL)然后对deals唯一索引扫描eq_refselect * from deals, user_trades where deals.id=user_trades.deal_id;select * from ref_table,other_table where ref_table.key_column_part1=other_table.column and ref_table.key_column_part2=1;ref:非唯一性索引扫描,返回匹配某个单独值的所有行。常见于使用非唯一索引即唯一索引的非唯一前缀进行的查找ref_or_null: 这种连接类型类似 ref,不同的是mysql会在检索的时候额外的搜索包含null值的记录select * from ref_table where key_column=expr or key_column is null;unique_subquery: in中使用主键查询的子查询value in (select primary_key from single_table where some_expr)index_subquery: 这种连接类型类似 unique_subquery。不过它用于在子查询中没有唯一索引的情况下:value in (select key_column from single_table where some_expr)range:索引范围扫描,对索引的扫描开始于某一点,返回匹配值域的行,常见于between, <, >, in, like 等的查询index: Full Index Scan,index与ALL区别为index类型只遍历索引树ALL:Full Table Scan, MySQL将遍历全表以找到匹配的行
稿源:勤快学QKXue.NET
更多Mysql 架构和索引介绍
Mysql 架构和索引
标签:
小编还为您整理了以下内容,可能对您也有帮助:
mysql的索引结构是怎么样的
MySQL索引类型包括:
(1)普通索引
这是最基本的索引,它没有任何*。它有以下几种创建方式:
◆创建索引
CREATE INDEX indexName ON mytable(username(length)); 如果是CHAR,VARCHAR类型,length可以小于字段实际长度;如果是BLOB和TEXT类型,必须指定 length,下同。
◆修改表结构
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;
(2)唯一索引
它与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。它有以下几种创建方式:
◆创建索引
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)) );
(3)主键索引
它是一种特殊的唯一索引,不允许有空值。一般是在建表的时候同时创建主键索引:
CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, PRIMARY KEY(ID) ); 当然也可以用 ALTER 命令。记住:一个表只能有一个主键。
(4)组合索引
为了形象地对比单列索引和组合索引,为表添加多个字段:
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); 建表时,usernname长度为 16,这里用 10。这是因为一般情况下名字的长度不会超过10,这样会加速索引查询速度,还会减少索引文件的大小,提高INSERT的更新速度。
如果分别在 usernname,city,age上建立单列索引,让该表有3个单列索引,查询时和上述的组合索引效率也会大不一样,远远低于我们的组合索引。虽然此时有了三个索引,但MySQL只能用到其中的那个它认为似乎是最有效率的单列索引。
mysql的索引结构是怎么样的
MySQL索引类型包括:
(1)普通索引
这是最基本的索引,它没有任何*。它有以下几种创建方式:
◆创建索引
CREATE INDEX indexName ON mytable(username(length)); 如果是CHAR,VARCHAR类型,length可以小于字段实际长度;如果是BLOB和TEXT类型,必须指定 length,下同。
◆修改表结构
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;
(2)唯一索引
它与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。它有以下几种创建方式:
◆创建索引
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)) );
(3)主键索引
它是一种特殊的唯一索引,不允许有空值。一般是在建表的时候同时创建主键索引:
CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, PRIMARY KEY(ID) ); 当然也可以用 ALTER 命令。记住:一个表只能有一个主键。
(4)组合索引
为了形象地对比单列索引和组合索引,为表添加多个字段:
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); 建表时,usernname长度为 16,这里用 10。这是因为一般情况下名字的长度不会超过10,这样会加速索引查询速度,还会减少索引文件的大小,提高INSERT的更新速度。
如果分别在 usernname,city,age上建立单列索引,让该表有3个单列索引,查询时和上述的组合索引效率也会大不一样,远远低于我们的组合索引。虽然此时有了三个索引,但MySQL只能用到其中的那个它认为似乎是最有效率的单列索引。
MySQL如何使用索引 较为详细的分析和例子_MySQL
在数据库表中,使用索引可以大大提高查询速度。假如我们创建了一个 testIndex表:
CREATE TABLE testIndex(i_testID INT NOT NULL,vc_Name VARCHAR(16) NOTNULL);
我们随机向里面插入了 1000条记录,其中有一条 i_testID vc_Name 555 erquan
在查找 vc_Name="erquan"的记录 SELECT *FROM testIndex WHERE vc_Name='erquan'; 时,如果在vc_Name 上已经建立了索引,MySql 无须任何扫描,即准确可找到该记录!相反,MySql 会扫描所有记录,即要查询 1000。以索引将查询速度提高 100 倍。
一、索引分单列索引和组合索引
单列索引:即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引。组合索引:即一个索包含多个列。
二、介绍一下索引的类型
1、普通索引。
这是最基本的索引,它没有任何。它有以下几种创建方式:
(1)创建索引:CREATE INDEX indexName ONtableName(tableColumns(length));如果是CHAR,VARCHAR类型,length可以小于字段实际长度;如果是 BLOB 和 TEXT 类型,必须指定 length,下同。
(2)修改表结构:ALTER tableName ADD INDEX[indexName] ON (tableColumns(length))
(3)创建表的时候直接指定:CREATE TABLE tableName ( [...],INDEX [indexName] (tableColumns(length)) ;
2、唯一索引。
它与前面的"普通索引"类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。它有以下几种创建方式:
(1)创建索引:CREATE UNIQUE INDEX indexName ONtableName(tableColumns(length))
(2)修改表结构:ALTER tableName ADD UNIQUE[indexName] ON (tableColumns(length))
(3)创建表的时候直接指定:CREATE TABLE tableName ( [...],UNIQUE [indexName] (tableColumns(length));
3、主键索引
它是一种特殊的唯一索引,不允许有空值。一般是在建表的时候同时创建主键索引:CREATE TABLE testIndex(i_testID INT NOT NULL AUTO_INCREMENT,vc_NameVARCHAR(16) NOT NULL,PRIMARY KEY(i_testID));当然也可以用ALTER 命令。记住:一个表只能有一个主键。
4、全文索引
MySQL从 3.23.23 版开始支持全文索引和全文检索。
删除索引的语法:DROP INDEX index_name ON tableName
三、单列索引和组合索引
为了形象地对比两者,再建一个表:
CREATE TABLE myIndex ( i_testID INT NOT NULL AUTO_INCREMENT, vc_NameVARCHAR(50) NOT NULL, vc_City VARCHAR(50) NOT NULL, i_Age INT NOT NULL,i_SchoolID INT NOT NULL, PRIMARY KEY (i_testID) );
在这 10000条记录里面 7 上 8 下地分布了 5 条 vc_Name="erquan" 的记录,只不过 city,age,school 的组合各不相同。
来看这条 T-SQL:SELECT i_testID FROM myIndex WHEREvc_Name='erquan' AND vc_City='郑州' AND i_Age=25;
首先考虑建单列索引:
在 vc_Name列上建立了索引。执行 T-SQL 时,MYSQL 很快将目标锁定在了 vc_Name=erquan 的 5 条记录上,取出来放到一中间结果集。在这个结果集里,先排除掉 vc_City 不等于"郑州"的记录,再排除 i_Age 不等于 25 的记录,最后筛选出唯一的符合条件的记录。
虽然在 vc_Name上建立了索引,查询时MYSQL不用扫描整张表,效率有所提高,但离我们的要求还有一定的距离。同样的,在 vc_City 和 i_Age 分别建立的单列索引的效率相似。
为了进一步榨取 MySQL的效率,就要考虑建立组合索引。就是将 vc_Name,vc_City,i_Age 建到一个索引里:
ALTER TABLE myIndex ADD INDEX name_city_age(vc_Name(10),vc_City,i_Age);
建表时,vc_Name长度为 50,这里为什么用 10 呢?因为一般情况下名字的长度不会超过 10,这样会加速索引查询速度,还会减少索引文件的大小,提高 INSERT 的更新速度。
执行 T-SQL时,MySQL 无须扫描任何记录就到找到唯一的记录!!
肯定有人要问了,如果分别在 vc_Name,vc_City,i_Age 上建立单列索引,让该表有 3 个单列索引,查询时和上述的组合索引效率一样吗?大不一样,远远低于我们的组合索引。虽然此时有了三个索引,但 MySQL 只能用到其中的那个它认为似乎是最有效率的单列索引。
建立这样的组合索引,其实是相当于分别建立了
vc_Name,vc_City,i_Age
vc_Name,vc_City
vc_Name
这样的三个组合索引!为什么没有 vc_City,i_Age 等这样的组合索引呢?这是因为 mysql 组合索引“最左前缀”的结果。简单的理解就是只从最左面的开始组合。并不是只要包含这三列的查询都会用到该组合索引,下面的几个 T-SQL 会用到:
SELECT * FROM myIndex WHREE vc_Name="erquan" ANDvc_City="郑州"
SELECT * FROM myIndex WHREEvc_Name="erquan"
而下面几个则不会用到:
SELECT * FROM myIndex WHREE i_Age=20 AND vc_City="郑州"
SELECT * FROM myIndex WHREE vc_City="郑州"
四、使用索引
到此你应该会建立、使用索引了吧?但什么情况下需要建立索引呢?一般来说,在 WHERE和 JOIN 中出现的列需要建立索引,但也不完全如此,因为 MySQL 只对 =,BETWEEN,IN,以及某些时候的LIKE(后面有说明)才会使用索引。
SELECT t.vc_Name FROM testIndex t LEFT JOIN myIndex m ONt.vc_Name=m.vc_Name WHERE m.i_Age=20 AND m.vc_City='郑州'时,有对 myIndex 表的 vc_City 和 i_Age 建立索引的需要,由于testIndex 表的 vc_Name 开出现在了 JOIN 子句中,也有对它建立索引的必要。
刚才提到了,只有某些时候的 LIKE才需建立索引?是的。因为在以通配符 % 和 _ 开头作查询时,MySQL 不会使用索引,如 SELECT * FROM myIndex WHERE vc_Name like'erquan%'
会使用索引,而 SELECT * FROM myIndex WHEREt vc_Namelike'%erquan' 就不会使用索引了。
五、索引的不足之处
上面说了那么多索引的好话,它真的有像传说中那么优秀么?当然会有缺点了。
1、虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行 INSERT、UPDATE 和DELETE。因为更新表时,MySQL 不仅要保存数据,还要保存一下索引文件。
2、建立索引会占用磁盘空间的索引文件。一般情况这个问题不太严重,但如果你在一个大表上创建了多种组合索引,索引文件的会膨胀很快。
讲了这么多,无非是想利用索引提高数据库的执行效率。不过索引只是提高效率的一个因素。如果你的MySQL有大数据的表,就需要花时间研究建立最优秀的索引或优化查询语句。
请问mysql索引,有主键索引、唯一索引、全文索引、组合索引、普通索引,他们分别的数据结构是什么?
普通索引:最基本的索引,没有任何
唯一索引:与"普通索引"类似,不同的就是:索引列的值必须唯一,但允许有空值。
主键索引:它 是一种特殊的唯一索引,不允许有空值。
全文索引:仅可用于 MyISAM 表,针对较大的数据,生成全文索引很耗时好空间。
组合索引:为了更多的提高mysql效率可建立组合索引,遵循”最左前缀“原则。
MyISAM中索引检索的算法为首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,则取出其data域的值,然后以data域的值为地址,读取相应数据记录。在MyISAM中,主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求key是唯一的,而辅助索引的key可以重复。
InnoDB的数据文件本身就是索引文件。InnoDB的辅助索引data域存储相应记录主键的值而不是地址。
聚集索引这种实现方式使得按主键的搜索十分高效,但是辅助索引搜索需要检索两遍索引:首先检索辅助索引获得主键,然后用主键到主索引中检索获得记录。