服务器学习心得


索引一些问题

<h2>设计出更高效的索引</h2> <h4>1. 选择唯一性索引</h4> <ul> <li>唯一性索引的值是唯一的,可以更快速的通过该索引来确定某条记录。 <ul> <li>例如,学生表中学号是具有唯一性的字段。</li> </ul></li> <li>为该字段建立唯一性索引可以很快的确定某个学生的信息。</li> <li>如果使用姓名的话,可能存在同名现象,从而降低查询速度。</li> </ul> <h4>2. 为经常需要排序、分组和联合操作的字段建立索引</h4> <ul> <li>经常需要 ORDER BY、GROUP BY、DISTINCT 和 UNION 等操作的字段,排序操作会浪费很多时间。</li> <li>如果为其建立索引,可以有效地避免排序操作。</li> </ul> <h4>3. 为常作为查询条件的字段建立索引</h4> <ul> <li>如果某个字段经常用来做查询条件,那么该字段的查询速度会影响整个表的查询速度。</li> <li>因此,为这样的字段建立索引,可以提高整个表的查询速度。</li> <li>注意:常查询条件的字段不一定是所要选择的列,换句话说,最适合索引的列是出现在 WHERE 子句中的列,或连接子句中指定的列,而不是出现在 SELECT 关键字后的选择列表中的列。</li> </ul> <h4>4. 限制索引的数目</h4> <ul> <li>索引的数目不是“越多越好”。每个索引都需要占用磁盘空间,索引越多,需要的磁盘空间就越大。 <ul> <li>在修改表的内容时,索引必须进行更新,有时还可能需要重构。</li> <li>因此,索引越多,更新表的时间就越长。</li> </ul></li> <li>如果有一个索引很少利用或从不使用,那么会不必要地减缓表的修改速度。</li> <li>此外,MySQL 在生成一个执行计划时,要考虑各个索引,这也要花费时间。</li> <li>创建多余的索引给查询优化带来了更多的工作。</li> <li>索引太多,也可能会使 MySQL 选择不到所要使用的最佳索引。</li> </ul> <h4>5. 尽量使用数据量少的索引</h4> <ul> <li>如果索引的值很长,那么查询的速度会受到影响。</li> <li>例如,对一个 CHAR(100) 类型的字段进行全文检索需要的时间肯定要比对 CHAR(10) 类型的字段需要的时间要多。</li> </ul> <h4>6. 数据量小的表最好不要使用索引</h4> <ul> <li>由于数据较小,查询花费的时间可能比遍历索引的时间还要短,索引可能不会产生优化效果。</li> </ul> <h4>7. 尽量使用前缀来索引</h4> <ul> <li>如果索引字段的值很长,最好使用值的前缀来索引。</li> <li>例如,TEXT 和 BLOG 类型的字段,进行全文检索会很浪费时间。</li> <li>如果只检索字段的前面的若干个字符,这样可以提高检索速度。</li> </ul> <h4>8. 删除不再使用或者很少使用的索引</h4> <ul> <li>表中的数据被大量更新,或者数据的使用方式被改变后,原有的一些索引可能不再需要。</li> <li>应该定期找出这些索引,将它们删除,从而减少索引对更新操作的影响。</li> </ul> <h2>索引到底对查询速度有什么影响</h2> <ul> <li>多数情况下,查询速度很慢时,加上索引便能解决问题。</li> <li>但是如果你不使用索引,在许多情况下,尝试通过其它途径来提高性能都纯粹是在浪费时间。</li> <li>应该首先使用索引来最大程度的改善性能,然后再看看是否还有其它有用的技术。</li> <li>索引提供了高效访问数据的方法,能够快速的定位表中的某条记录,加快数据库查询的速度,从而提高数据库的性能。</li> <li>如果查询时不使用索引,那么查询语句将查询表中的所有字段。这样查询的速度会很慢。</li> <li>使用索引进行查询,查询语句不必读完表中的所有记录,而只查询索引字段。</li> <li>这样可以减少查询的记录数,达到提高查询速度的目的。</li> </ul> <h4>实例</h4> <ul> <li>对比使用索引和不使用索引来分析索引对查询速度的影响</li> </ul> <pre><code class="language-mysql">CREATE TABLE `tb_students_info` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(25) NOT NULL DEFAULT '' COMMENT '姓名', PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COMMENT='学生信息'; # 插入数据 INSERT INTO `test`.`tb_students_info` (`id`, `name`) VALUES ('1', '张三'); INSERT INTO `test`.`tb_students_info` (`id`, `name`) VALUES ('2', '李四'); INSERT INTO `test`.`tb_students_info` (`id`, `name`) VALUES ('3', '王五'); INSERT INTO `test`.`tb_students_info` (`id`, `name`) VALUES ('4', '赵六'); INSERT INTO `test`.`tb_students_info` (`id`, `name`) VALUES ('5', '周七'); INSERT INTO `test`.`tb_students_info` (`id`, `name`) VALUES ('6', '吴八'); INSERT INTO `test`.`tb_students_info` (`id`, `name`) VALUES ('7', '朱九'); INSERT INTO `test`.`tb_students_info` (`id`, `name`) VALUES ('8', '苏十');</code></pre> <ul> <li>使用 EXPLAIN 分析未使用索引时的查询情况</li> </ul> <pre><code class="language-mysql">EXPLAIN SELECT * FROM tb_students_info WHERE name='张三' \G;</code></pre> <ul> <li>由结果可以看到,rows 列的值是 8,说明查询语句扫描了表中的 8 条记录。</li> <li>没有索引的表就相当于一组无序的行,如果我们想找到某条记录就必须检查表的每一行,看看它是否与那个期望值相匹配。</li> <li> <p>这是一个全表扫描操作,其效率很低,如果表很大,而且仅有少数几条记录与搜索条件相匹配,那么整个扫描过程的效率将会超级低。</p> </li> <li>在 tb_students_info 表的 name 字段添加索引</li> </ul> <pre><code class="language-mysql">CREATE INDEX index_name ON tb_students_info(name);</code></pre> <ul> <li>使用 EXPLAIN 再次执行上面的查询语句</li> </ul> <pre><code class="language-mysql">EXPLAIN SELECT * FROM tb_students_info WHERE name='张三' \G;</code></pre> <ul> <li>结果显示,rows 列的值为 1,表示这个查询语句只扫描了表中的 1 条记录。</li> <li>创建索引后访问的行由 8 行减少到 1 行,其查询速度自然比扫描 8 条记录快。</li> <li>而且 possible_keys 和 key 的值都是 index_name,这说明查询时使用了 index_name 索引。</li> <li>所以,在查询操作中,使用索引不仅能自动优化查询效率,还会降低服务器的开销。</li> </ul> <h4>注意:</h4> <ul> <li>由于 tb_students_info 表中记录较少,所以在这没有分析运行时间。</li> <li>表中记录多时,运行时间的差异也会体现出索引对查询速度的影响。</li> </ul> <h2>索引在什么情况下不会被使用</h2> <h4>查询语句中使用LIKE关键字</h4> <ul> <li>在查询语句中使用 LIKE 关键字进行查询时,如果匹配字符串的第一个字符为“%”,索引不会被使用。</li> <li>如果“%”不是在第一个位置,索引就会被使用。</li> </ul> <h4>查询语句中使用多列索引</h4> <ul> <li>多列索引是在表的多个字段上创建一个索引,只有查询条件中使用了这些字段中的第一个字段,索引才会被使用。</li> </ul> <h4>查询语句中使用OR关键字</h4> <ul> <li>查询语句只有 OR 关键字时,如果 OR 前后的两个条件的列都是索引,那么查询中将使用索引。</li> <li>如果 OR 前后有一个条件的列不是索引,那么查询中将不使用索引。</li> </ul> <h2>索引注意事项</h2> <h4>创建索引</h4> <ul> <li>对于查询为主的应用来说,创建索引非常重要。</li> <li>很多时候性能问题是因为忘添加索引造成的,或没有添加有效的索引卖到的。</li> <li>不加索引,在查找数据会进行一次全表扫描,如果一张表的数据量很大,并且符合条件的结果很少,会引导致性能下降。</li> <li>不是什么情况都非得建索引不可,比如性别可能就只有两个值,建索引不仅没什么优势,还会影响到更新速度,这被称为过度索引。</li> </ul> <h4>复合索引</h4> <ul> <li>创建复合索引时应该将最常用作限制条件的列放在最左边,依次递减</li> </ul> <pre><code class="language-mysql">select * from users where area=’shanghai’ and age=17</code></pre> <ul> <li>area和age分别创建单个索引,由于mysql查询每次只能使用一个索引</li> <li>如果在area、age两列上创建复合索引效率更高</li> </ul> <h4>索引不会包含有NULL值的列</h4> <ul> <li>只要列中包含有NULL值,索引无效。</li> <li>在数据库设计时,字段要设置一个非NULL的默认值,如空字符串,0等</li> </ul> <h4>使用短索引</h4> <ul> <li>对字符串列进行索引,应该指定一个前缀长度。</li> <li>如一个CHAR(255)列,在前10 个或20 个字符内,多数值是惟一的,就不要将整个列进行索引。</li> <li>短索引不仅可以提高查询速度,还可以节省磁盘空间和I/O操作。</li> </ul> <h4>排序的索引问题</h4> <ul> <li>mysql查询只使用一个索引,如果where子句中已经使用索引,order by中的列不会使用索引。</li> </ul> <h4>like语句操作</h4> <ul> <li>like “%name%” 不会使用索引,like “name%”可以使用索引</li> </ul> <h4>不要在列上进行运算</h4> <h4>不使用NOT IN操作</h4> <ul> <li>NOT IN操作不会使用索引,将进行全表扫描。</li> <li>NOT IN可以用NOT EXISTS代替</li> </ul>

页面列表

ITEM_HTML