一、数据库索引
1.MySQL 索引可以分为单列索引、复合索引、唯一索引、主键索引等
#创建索引的两种方式
CREATE [UNIQUE] INDEX index_name ON table_name(index_col_name[,...]);
ALTER TABLE table_name ADD [UNIQUE] INDEX index_name ON (index_col_name[,...]);
2.关于索引使用的几个原则
WHERE子句中的列可能最适合做为索引
不要尝试为性别或者有无这类字段等建立索引(因为类似性别的列,一般只含有“0”和“1”,无论搜索结果如何都会大约得出一半的数据)
如果创建复合索引,要遵守最左前缀法则。即查询从索引的最左前列开始,并且不跳过索引中的列
不要过度使用索引。每一次的更新,删除,插入都会维护该表的索引,更多的索引意味着占用更多的空间
使用InnoDB存储引擎时,记录(行)默认会按照一定的顺序存储,如果已定义主键,则按照主键顺序存储,由于普通索引都会保存主键的键值,因此主键应尽可能的选择较短的数据类型,以便节省存储空间
不要尝试在索引列上使用函数。
二、锁以及事务的隔离级别
1.两种类型的锁
共享锁(读锁)
将对象数据变为只读对象的锁定,允许多个用户进程同时访问数据,但在锁释放前无法修改数据。排他锁(写锁)
在数据对象进行变更时锁定,不允许其他用户进程访问和修改数据,保证了数据完整性。
mysql包含两种类型的执行引擎InnoDB和MyISAM。InnoDB行锁是通过给索引上的索引项加锁来实现的,也就是说,只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁。MyISAM只支持表锁,不提供事物支持,性能比InnoDB高上一些。
- mysql中的显示加锁语法
-- 共享锁(S)
SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE;
-- 排他锁(X)
SELECT * FROM table_name WHERE ... FOR UPDATE;
# FOR UPDATE仅适用于InnoDB,且必须在交易区块(BEGIN/COMMIT)中才能生效。
# 当使用FOR UPDATE时WHERE条件语句未用到索引时将造成表锁。
- 索引选择性:Selectivity
索引的选择性(Selectivity),是指不重复的索引值(也叫基数,Cardinality)与表记录数(#T)的比值:index Selectivity = Cardinality / #T
显然选择性的取值范围为(0, 1],选择性越高的索引价值越大,这是由B+Tree的性质决定的。简单来说就是我们在选择哪些字段作为索引列的时候要考虑当前列的数据重复率是否很高,如果数据重复率特别高那么设置索引的意义并不大,反而会影响数据写入的效率。
//统计索引选择性
SELECT count(DISTINCT(concat(first_name, left(last_name, 4))))/count(*) AS Selectivity FROM mem_user;
2.四种隔离级别
READ_UNCOMMITTED(读未提交)
事物未提交时可以被其他事物读取,会出现脏读、不可重复读、幻读现象READ_UNCOMMITTED(读已提交,锁定正在读取的行)
事物提交后可被其他事物读取,可以避免脏读,会出现不可重复读、幻读现象。REPEATABLE_READ(可重复读,锁定读取的所有行,mysql默认事物隔离级别)
可以防止脏读、不可重复读,但会出幻读。SERIALIZABLE(可串行化)
事物被处理为顺序执行,效率低下。
隔离级别越高,数据的完整性也就越高,但同时运行性下降,相反如果隔离级别越低数据完整性越低,同时运行性也就提高了,笔者在实际工作当中遇到了许多关于事物隔离级别导致的问题。所以在不同的应用场景下设置合理的隔离级别是非常重要的。