博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
mysql索引创建
阅读量:6672 次
发布时间:2019-06-25

本文共 9304 字,大约阅读时间需要 31 分钟。

hot3.png

mysql数据查询总结

昨天新增会员数目:select * from member where createTime >= DATE_FORMAT(date_sub(current_date(),interval 1 day),'%Y-%m-%d 00:00:00') and createTime <=DATE_FORMAT(now(),'%Y-%m-%d 00:00:00')查询当前月份的数据select * from member  where date_format(createTime,'%Y-%m')=date_format(now(),'%Y-%m')查询上个月的数据select * from member   where date_format(createTime,'%Y-%m')=date_format(DATE_SUB(curdate(), INTERVAL 1 MONTH),'%Y-%m')查询上一年的数据select * from member where DATE_FORMAT(createTime,'%Y-%m')=DATE_FORMAT(DATE_SUB(curdate(), INTERVAL 1 YEAR),'%Y-%m')

 

查询表中某个字段重复记录

select openId,count(*) from `t_subscribe_record` group by openId having count(*)>1
select * from user where name in (select name from user group by name having count(1) > 1);
select * from `gift_record` t1  where t1.`fromUserPhone` not in(select t2.`moblie` from `t_request_ip_record` t2 where type=0 )
(select `toUserPhone`from `gift_record` t1  where t1.`fromUserPhone` not in(select t2.`moblie` from `t_request_ip_record` t2 where type=0 ));   insert into `t_request_ip_record`(moblie) (select `toUserPhone`from `gift_record` t1  where t1.`fromUserPhone` not in(select t2.`moblie` from `t_request_ip_record` t2 where type=0 ));   update `t_request_ip_record` set type=0 where `ip` is null;  update `t_request_ip_record` set `ip`="124.78.92.140" where `ip` is null and type=0;    update `t_request_ip_record` set `ip_city`="上海市"   where  `ip`="124.78.92.140" and type=0 and `qr_code_value` is null;   select * from `t_request_ip_record` where `ip`="124.78.92.140" and type=0 and `qr_code_value` is null; select * from `t_request_ip_record` where `ip` is null;  delete from `t_request_ip_record` where `ip` is null;

 

 

一、MySQL索引类型:1、普通索引 这是最基本的索引类型,而且它没有唯一性之类的限制。普通索引可以通过以下几种方式创建: 创建索引,例如CREATE INDEX 
<索引的名字>
ON tablename (列的列表); 修改表,例如ALTER TABLE tablename ADD INDEX [索引的名字] (列的列表); 创建表的时候指定索引,例如CREATE TABLE tablename ( [...], INDEX [索引的名字] (列的列表) ); 2、唯一性索引 这种索引和前面的“普通索引”基本相同,但有一个区别:索引列的所有值都只能出现一次,即必须唯一。唯一性索引可以用以下几种方式创建: 创建索引,例如CREATE UNIQUE INDEX
<索引的名字>
ON tablename (列的列表); 修改表,例如ALTER TABLE tablename ADD UNIQUE [索引的名字] (列的列表); 创建表的时候指定索引,例如CREATE TABLE tablename ( [...], UNIQUE [索引的名字] (列的列表) ); 3、主键 主键是一种唯一性索引,但它必须指定为“PRIMARY KEY”。如果你曾经用过AUTO_INCREMENT类型的列,你可能已经熟悉主键之类的概念了。主键一般在创建表的时候指定,例如“CREATE TABLE tablename ( [...], PRIMARY KEY (列的列表) ); ”。但是,我们也可以通过修改表的方式加入主键,例如“ALTER TABLE tablename ADD PRIMARY KEY (列的列表); ”。每个表只能有一个主键。 4、全文索引 MySQL从3.23.23版开始支持全文索引和全文检索。在MySQL中,全文索引的索引类型为FULLTEXT。全文索引可以在VARCHAR或者TEXT类型的列上创建。它可以通过CREATE TABLE命令创建,也可以通过ALTER TABLE或CREATE INDEX命令创建。对于大规模的数据集,通过ALTER TABLE(或者CREATE INDEX)命令创建全文索引要比把记录插入带有全文索引的空表更快。二、单列索引与多列索引 索引可以是单列索引,也可以是多列索引。假设有这样一个people表: CREATE TABLE people ( peopleid SMALLINT NOT NULL AUTO_INCREMENT, firstname CHAR(50) NOT NULL,lastname CHAR(50) NOT NULL, age SMALLINT NOT NULL, townid SMALLINT NOT NULL,PRIMARY KEY (peopleid) ); 查找姓名为Mike Sullivan、年龄17岁用户的peopleidSQL命令为SELECT peopleid FROM people WHERE firstname='Mike' AND lastname='Sullivan' AND age=17;由于我们不想让MySQL每次执行查询就去扫描整个表,这里需要考虑运用索引。 首先,我们可以考虑在单个列上创建索引,比如firstname、lastname或者age列。如果我们创建firstname列的索引(ALTER TABLE people ADD INDEX firstname (firstname);),MySQL将通过这个索引迅速把搜索范围限制到那些firstname='Mike'的记录,然后再在这个“中间结果集”上进行其他条件的搜索:它首先排除那些lastname不等于“Sullivan”的记录,然后排除那些age不等于17的记录。当记录满足所有搜索条件之后,MySQL就返回最终的搜索结果。 由于建立了firstname列的索引,与执行表的完全扫描相比,MySQL的效率提高了很多,但MySQL扫描的记录数量仍旧远远超过了实际所需要的。虽然可以删除firstname列上的索引,再创建lastname或者age列的索引,但总地看来,不论在哪个列上创建索引搜索效率仍旧相似。 为了提高搜索效率,需要考虑运用多列索引。如果为firstname、lastname和age这三个列创建一个多列索引,MySQL只需一次检索就能够找出正确的结果!下面是创建这个多列索引的SQL命令: ALTER TABLE people ADD INDEX fname_lname_age (firstname,lastname,age); 由于索引文件以B-树格式保存,MySQL能够立即转到合适的firstname,然后再转到合适的lastname,最后转到合适的age。在没有扫描数据文件任何一个记录的情况下,MySQL就正确地找出了搜索的目标记录! 那么,如果在firstname、lastname、age这三个列上分别创建单列索引,效果是否和创建一个firstname、lastname、age的多列索引一样呢?答案是否定的,两者完全不同。当我们执行查询的时候,MySQL只能使用一个索引。如果你有三个单列的索引,MySQL会试图选择一个限制最严格的索引。但是,即使是限制最严格的单列索引,它的限制能力也肯定远远低于firstname、lastname、age这三个列上的多列索引。 1、最左前缀 多列索引还有另外一个优点,它通过称为最左前缀(Leftmost Prefixing)的概念体现出来。继续考虑前面的例子,现在有一个firstname、lastname、age列上的多列索引,当搜索条件是以下各种列的组合时,MySQL将使用fname_lname_age索引: firstname,lastname,age firstname,lastname firstname 从另一方面理解,它相当于创建了(firstname,lastname,age)、(firstname,lastname)以及(firstname)这些列组合上的索引。下面这些查询都能够使用这个fname_lname_age索引: SELECT peopleid FROM people WHERE firstname='Mike' AND lastname='Sullivan' AND age='17'; SELECT peopleid FROM people WHERE firstname='Mike' AND lastname='Sullivan'; SELECT peopleid FROM people WHERE firstname='Mike'; 下面的查询就完全不能使用这个索引: SELECT peopleid FROM people WHERE lastname='Sullivan'; SELECT peopleid FROM people WHERE age='17'; SELECT peopleid FROM people WHERE lastname='Sullivan' AND age='17'; 2、选择索引列 在性能优化过程中,选择在哪些列上创建索引是最重要的步骤之一。可以考虑使用索引的主要有两种类型的列:在WHERE子句中出现的列,在join子句中出现的列。请看下面这个查询: SELECT age FROM people WHERE firstname='Mike' AND lastname='Sullivan' 这个查询与前面的查询略有不同,但仍属于简单查询。由于age是在SELECT部分被引用,MySQL不会用它来限制列选择操作。因此,对于这个查询来说,创建age列的索引没有什么必要。下面是一个更复杂的例子: SELECT people.age, town.nameFROM people LEFT JOIN town ON people.townid=town.townidWHERE firstname='Mike'AND lastname='Sullivan'与前面的例子一样,由于firstname和lastname出现在WHERE子句中,因此这两个列仍旧有创建索引的必要。除此之外,由于town表的townid列出现在join子句中,因此需要考虑创建该列的索引。 那么,是否可以简单地认为应该索引WHERE子句和join子句中出现的每一个列呢?差不多如此,但并不完全。还必须考虑到对列进行比较的操作符类型。MySQL只有对以下操作符才使用索引:<,<=,=,>,>=,BETWEEN,IN,以及某些时候的LIKE。可以在LIKE操作中使用索引的情形是指另一个操作数不是以通配符(%或者_)开头的情形。例如,“SELECT peopleid FROM people WHERE firstname LIKE 'Mich%';”这个查询将使用索引,但“SELECT peopleid FROM people WHERE firstname LIKE '%ike';”这个查询不会使用索引。 3、分析索引效率现在我们已经知道了一些如何选择索引列的知识,但还无法判断哪一个最有效。MySQL提供了一个内建的SQL命令帮助我们完成这个任务,这就是EXPLAIN命令。EXPLAIN命令的一般语法是:EXPLAIN 。你可以在MySQL文档找到有关该命令的更多说明。下面是一个例子: EXPLAIN SELECT peopleid FROM people WHERE firstname='Mike' AND lastname='Sullivan' AND age='17'; 这个命令将返回下面这种分析结果: 下面我们就来看看这个EXPLAIN分析结果的含义。 table:这是表的名字。 type:连接操作的类型。下面是MySQL文档关于ref连接类型的说明: “对于每一种与另一个表中记录的组合,MySQL将从当前的表读取所有带有匹配索引值的记录。如果连接操作只使用键的最左前缀,或者如果键不是UNIQUE或PRIMARY KEY类型(换句话说,如果连接操作不能根据键值选择出唯一行),则MySQL使用ref连接类型。如果连接操作所用的键只匹配少量的记录,则ref是一种好的连接类型。” 在本例中,由于索引不是UNIQUE类型,ref是我们能够得到的最好连接类型。 如果EXPLAIN显示连接类型是“ALL”,而且你并不想从表里面选择出大多数记录,那么MySQL的操作效率将非常低,因为它要扫描整个表。你可以加入更多的索引来解决这个问题。预知更多信息,请参见MySQL的手册说明。 possible_keys: 可能可以利用的索引的名字。这里的索引名字是创建索引时指定的索引昵称;如果索引没有昵称,则默认显示的是索引中第一个列的名字(在本例中,它是“firstname”)。默认索引名字的含义往往不是很明显。 Key: 它显示了MySQL实际使用的索引的名字。如果它为空(或NULL),则MySQL不使用索引。 key_len: 索引中被使用部分的长度,以字节计。在本例中,key_len是102,其中firstname占50字节,lastname占50字节,age占2字节。如果MySQL只使用索引中的firstname部分,则key_len将是50。 ref: 它显示的是列的名字(或单词“const”),MySQL将根据这些列来选择行。在本例中,MySQL根据三个常量选择行。 rows: MySQL所认为的它在找到正确的结果之前必须扫描的记录数。显然,这里最理想的数字就是1。 Extra: 这里可能出现许多不同的选项,其中大多数将对查询产生负面影响。在本例中,MySQL只是提醒我们它将用WHERE子句限制搜索结果集。 索引的缺点 到目前为止,我们讨论的都是索引的优点。事实上,索引也是有缺点的。 首先,索引要占用磁盘空间。通常情况下,这个问题不是很突出。但是,如果你创建每一种可能列组合的索引,索引文件体积的增长速度将远远超过数据文件。如果你有一个很大的表,索引文件的大小可能达到操作系统允许的最大文件限制。 第二,对于需要写入数据的操作,比如DELETE、UPDATE以及INSERT操作,索引会降低它们的速度。这是因为MySQL不仅要把改动数据写入数据文件,而且它还要把这些改动写入索引文件。补充:MySQL建立部分索引代码--即短索引-- 计算部分索引平均值SELECT COUNT(DISTINCT t.show_sentence)/COUNT(1) from t_user_show t;-- 找出部分索引最佳长度(得到结果与平均值相近)SELECT COUNT(DISTINCT LEFT(t.show_sentence,10) )/COUNT(*) as sel10,COUNT(DISTINCT LEFT(t.show_sentence,20) )/COUNT(*) as sel20,COUNT(DISTINCT LEFT(t.show_sentence,30) )/COUNT(*) as sel30,COUNT(DISTINCT LEFT(t.show_sentence,40) )/COUNT(*) as sel40 from t_user_show t;平均值 == 得到结果与平均值相近-- 建部分索引语句ALTER TABLE t_user_show add key (show_sentence(40));force index()可以指定本次查询使用哪个索引select count(distinct openId) as count from t_table force index (IX_new_createTime) where createTime >= '2017-11-05' and createTime < '2017-11-06' and appId='wx3a69955f8cf7123'

三、选择索引的准则

1、搜索的索引列,不一定是所要选择的列 换句话说,最适合索引的列是出现在 WHERE 子句中的列,或连接子句中指定的列,而不是出现在 SELECT 关键字后的选择列表中的列,例如: SELECT col_a ←不适合作索引列 FROM Tbl1 LEFT JOIN tbl2 ON tbl1.col_b = tbl2.col_c ←适合作索引列 WHERE col_d = expr ←适合作索引列 当然,所选择的列和用于 WHERE 子句的列也可能是相同的。关键是,列出现在选择列表中不是该列应该索引的标志。 出现在连接子句中的列或出现在形如 col1 = col2 的表达式中的列是很适合索引的列。查询中的 col_b 和 col_c 就是这样的例子。 如果 MySQL 能利用连接列来优化一个查询,表示它通过消除全表扫描相当可观地减少了表行的组合。

2、使用惟一索引 考虑某列中值的分布。对于惟一值的列,索引的效果最好,而具有多个重复值的列,其索引效果最差。例如,存放年龄的列具有不同值,很容易区分各行。 而用来记录性别的列,只含有“M”和“F”,则对此列进行索引没有多大用处(不管搜索哪个值,都会得出大约一半的行)

3、使用短索引 如 果对串列进行索引,应该指定一个前缀长度,只要有可能就应该这样做。例如,如果有一个 CHAR(200) 列,如果在前 10 个或 20 个字符内,多数值是惟一的, 那么就不要对整个列进行索引。对前 10 个或 20 个字符进行索引能够节省大量索引空间,也可能会使查询更快。 较小的索引涉及的磁盘 I/O 较少,较短的值比较起来更快。更为重要的是,对于较短的键值,索引高速缓存中的块能容纳更多的键值, 因此,MySQL 也可以在内存中容纳更多的值。这增加了找到行而不用读取索引中较多块的可能性。 (当然,应该利用一些常识。如仅用列值的第一个字符进行索引是不可能有多大好处的,因为这个索引中不会有许多不同的值。)

4、利用最左前缀 在创建一个 n 列的索引时,实际是创建了 MySQL 可利用的 n 个索引。多列索引可起几个索引的作用,因为可利用索引中最左边的列集来匹配行。这样的列集称为最左前缀。 (这与索引一个列的前缀不同,索引一个列的前缀是利用该的前 n 个字符作为索引值。) 假如一个表在分别名为 state、city 和 zip 的三个列上有一个索引。 索引中的行是按 state/city/zip 的次序存放的,因此,索引中的行也会自动按 state/city 的顺序和 state 的顺序存放。这表示,即使在查询中只指定 state 值或只指定 state 和 city 的值, MySQL 也可以利用索引。 因此,此索引可用来搜索下列的列组合: MySQL 不能使用不涉及左前缀的搜索。例如,如果按 city 或 zip 进行搜索,则不能使用该索引。如果要搜索某个州以及某个 zip 代码(索引中的列1和列3), 则此索引不能用于相应值的组合。但是,可利用索引来寻找与该州相符的行,以减少搜索范围

5、不要过度索引 不要以为索引“越多越好”,什么东西都用索引是错的。每个额外的索引都要占用额外的磁盘空间,并降低写操作的性能,这一点我们前面已经介绍过。 在修改表的内容时,索引必须进行更新,有时可能需要重构,因此,索引越多,所花的时间越长。 如果有一个索引很少利用或从不使用,那么会不必要地减缓表的修改速度。此外,MySQL 在生成一个执行计划时,要考虑各个索引,这也要费时间。 创建多余的索引给查询优化带来了更多的工作。索引太多,也可能会使 MySQL 选择不到所要使用的最好索引。只保持所需的索引有利于查询优化。 如果想给已索引的表增加索引,应该考虑所要增加的索引是否是现有多列索引的最左索引。如果是,则就不要费力去增加这个索引了,因为已经有了

 6、考虑在列上进行的比较类型 索引可用于“<”、“<=”、“=”、“>=”、“>”和 BETWEEN 运算。在模式具有一个直接量前缀时,索引也用于 LIKE 运算。如果只将某个列用于其他类型的运算时(如 STRCMP( )),对其进行索引没有价值。

 

 

转载于:https://my.oschina.net/chenxiaobian/blog/726141

你可能感兴趣的文章
稀疏矩阵的压缩存储和转置
查看>>
华为S5700交换机开启WEB配置
查看>>
mysql主从同步错误解决和Slave_IO_Running: NO
查看>>
Coding and Paper Letter(十七)
查看>>
感谢51CTO提供这个平台让我可以分享“姿势”
查看>>
Toast 自定义位置和带图
查看>>
outlook设置gmail邮箱报错:Outlook 无法连接到接收(POP3)电子邮件服务器
查看>>
linux中文件的常用操作
查看>>
php rabbitmq操作类及生产者和消费者实例代码
查看>>
C# 面向对象三大特征 的简单描述
查看>>
Tomcat服务器集群与负载均衡实现
查看>>
我的友情链接
查看>>
crontab使用进程锁flock解决冲突
查看>>
MySQL 5.6 for Windows 解压缩版配置安装
查看>>
linux使用ntfs-3g 挂载NTFS分区
查看>>
森林、域树、域之间的关系? AD与站点之间的关系?
查看>>
shell脚本中执行时提示“没有那个文件或目录”的解决办法
查看>>
手机/移动前端开发需要注意的20个要点
查看>>
[css]vw
查看>>
性能下降曲线
查看>>