MySQL简单使用

NORMAL 普通索引
UNIQUE 唯一索引
FULLTEXT 全文索引
SPATIAL 空间索引
显示某张表有哪些索引
SHOW INDEX FROM 表名
最左前缀匹配原则
### 当b+树的数据项是复合的数据结构,比如(name,age,sex)的时候,b+数是按照从左到右的顺序来建立搜索树的,
### 比如当(张三,20,F)这样的数据来检索的时候,b+树会优先比较name来确定下一步的所搜方向,如果name相同再依次比较age和sex,最后得到检索的数据;
### 但当(20,F)这样的没有name的数据来的时候,b+树就不知道下一步该查哪个节点,因为建立搜索树的时候name就是第一个比较因子,必须要先根据name来搜索才能知道下一步去哪里查询。
### 比如当(张三,F)这样的数据来检索时,b+树可以用name来指定搜索方向,但下一个字段age的缺失,所以只能把名字等于张三的数据都找到,然后再匹配性别是F的数据了, 这个是非常重要的性质,即索引的最左匹配特性
使用索引的原则
/**
1.最左前缀匹配原则,非常重要的原则,mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整。

2.=和in可以乱序,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式。

3.尽量选择区分度高的列作为索引,区分度的公式是count(distinct col)/count(*),表示字段不重复的比例,比例越大我们扫描的记录数越少,唯一键的区分度是1,而一些状态、性别字段可能在大数据面前区分度就是0,那可能有人会问,这个比例有什么经验值吗?使用场景不同,这个值也很难确定,一般需要join的字段我们都要求是0.1以上,即平均1条扫描10条记录。

4.索引列不能参与计算,保持列“干净”,比如from_unixtime(create_time) = ’2014-05-29’就不能使用到索引,原因很简单,b+树中存的都是数据表中的字段值,但进行检索时,需要把所有元素都应用函数才能比较,显然成本太大。所以语句应该写成create_time = unix_timestamp(’2014-05-29’)。

5.尽量的扩展索引,不要新建索引。比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可。
*/
查询优化的7个步骤
## 0.先运行看看是否真的很慢,注意设置SQL_NO_CACHE

## 1.where条件单表查,锁定最小返回记录表。这句话的意思是把查询语句的where都应用到表中返回的记录数最小的表开始查起,单表每个字段分别查询,看哪个字段的区分度最高
                                    select count(*),sync_status from stage_poi  group by sync_status

## 2.explain查看执行计划,是否与1预期一致(从锁定记录较少的表开始查询),

3.order by limit 形式的sql语句让排序的表优先查

4.了解业务方使用场景

## 5.加索引时参照建索引的几大原则

必须要掌握的SQL语句

查询总的条数
<!-- long countDemandNumber(); -->
    <select id="countDemandNumber" resultType="long">
        select count(*) from demand_order where status = 4
    </select>
将某个数字类型的字段,加起来,求和
 <!-- public long CountDemandProcurement(); -->
    <select id="countDemandProcurement" resultType="long">
        select sum(coalNumber) from demand_order where status = 4
    </select>

<!-- 
    需要特别注意的是,假如没有一条数据符合条件,
    那么返回的将会是一个NULL,
    与要求返回的Long类型不服
    报错

    解决方案:一般实在Service层来处理
    使用该SQL语句之前
    前去执行 select count(*) from demand_order where status = 4
    假如返回的是0,代表没有一条数据符合条件,就不执行该SQL语句
    假如返回的是非0,代表至少有一条数据符合条件,就可以执行该SQL语句
-->
多表连接查询,通过公共列(尽管在不同表中名字可能不同,但是类型和代表的意思是相同的)
<!-- public long regionalCoalDistribution(String producingArea,String coalType); -->
    <select id="regionalCoalDistribution" resultType="long">
        select sum(q.supplyQuantity) from quoted_price_info as q inner join demand_order as d on q.dId=d.id
        where q.producingArea = #{param1} and d.coalType=#{param2}
    </select>

<!-- 
    这里使用的连接方式是: inner join
    建议使用: inner join
-->
计算查询出来的某一列的平均值
<!-- 平均值 -->
    <select id="***" resultType="***">
        select avg(id) from quoted_price_info
    </select>

<!-- 
    注意计算平均值的列的字段类型,是数字类型 
-->
查询某列的最大/小值

<!-- 查询某列的最大值 -->
    <select id="***" resultType="***">
        select max(id) from quoted
    </select>

<!-- 查询某列的最小值 -->
    <select id="***" resultType="***">
        select max(id) from quoted
    </select>

<!-- 
    注意计算平均值的列的字段类型,是数字类型 
-->
在SQL语句中也可以进行分页
<!-- 分页 -->
    <select id="***" resultType="***">
        select * from quoted limit 0,10
    </select>

<!-- 
     limit说明:
    有两个参数,
    参数1:代表第几页,从0开始
    参数2:代表
-->
group by进行分组,可以搭配having使用
<!-- 雷达图public List<RadarMapVO> attention(); -->
    <select id="attention" resultType="team1.deal.model.vo.RadarMapVO">
        select coalType,producingArea,sum(supplyQuantity) as count 
        from (
        select d.coalType,q.producingArea,q.supplyQuantity
        from quoted_price_info as q inner join demand_order as d on q.did = d.id
        where q.producingArea = '沿海城市' or q.producingArea = '内陆城市'
        group by q.producingArea,q.id
        ) as table1 
        group by producingArea,coalType
    </select>
<!-- 搭配having使用 -->
    <select id="***" resultType="***">
        select *,count(*) from quoted group by producingArea having port = '广东'
    </select>

group by
    //:对select查询出来的结果集按照某个字段或者表达式进行分组,获得一组组的集合,然后从每组中取出一个指定字段或者表达式的值
    
    注意:
    如果分组后,使用select 字段1,字段2,...查询出来的只要有一个字段的值是不同的,MySQL就会迷惑,因为MySQL需要向用户返回展示分组中的一条数据,所以现在MySQL就不知道返回那一条数据,
    如果分组后,使用select 字段1,字段2,...查询出来的所有字段的值都是相同的,MySQL就会立马返回一条数据,因为所有的字段都是一样的
使用ORDER BY根据某个字段进行升序或者降序
<!-- 根据id降序排列 -->
    <select id="***" resultType="***">
        select * from quoted_price_info order by id DESC
    </select>

<!-- 
    特别说明:
    1.降序排列:order by 字段名 DESC
    2.升序排列:order by 字段名 ASC,MySQL默认是升序排列,所以一般情况下是不使用的

    字段类型一般是数字类型
-->
当涉及到时间时,比如说只查询某个时间段的数据时
<!-- public List<String> kindsOfCoallist(LocalDateTime beginYear,LocalDateTime endYear); -->
    <select id="kindsOfCoallist" resultType="String">
        select coalType from demand_order where deliveryTime <![CDATA[>=]]> #{beginYear}
        and deliveryTime <![CDATA[<]]> #{endYear} group by coalType
    </select>

<!-- 
    时间在MySQL数据库中是以timestamp时间戳的方式存储,只不过在navicat中是以yyyy-MM-dd HH:mm:ss格式展示
    
    时间的比较不能像普通的数字比较那样直接使用>  <   <=  >=...
    必须使用<![CDATA[>]]>   <![CDATA[<]]>   <![CDATA[<=]]>  <![CDATA[>=]]>....
-->
条件操作符
<>, !=
    不等于,检测两个值是否相等,如果不相等返回true
    
<=>
    : 比较操作符(不同于 = 运算符),当比较的的两个值相等或者都为 NULL 时返回 true。
        
NULL 值的处理
/**NULL 的条件比较运算是比较特殊的。你不能使用 = NULL 或 != NULL 在列中查找 NULL 值 。

在 MySQL 中,NULL 值与任何其它值的比较(即使是 NULL)永远返回 NULL,即 NULL = NULL 返回 NULL 。

MySQL 中处理 NULL 使用 IS NULL 和 IS NOT NULL 运算符*/

正则表达式

说明
模式 描述
^ 匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性,^ 也匹配 '\n' 或 '\r' 之后的位置
$ 匹配输入字符串的结束位置。如果设置了RegExp 对象的 Multiline 属性,$ 也匹配 '\n' 或 '\r' 之前的位置
. 匹配除 "\n" 之外的任何单个字符。要匹配包括 '\n' 在内的任何字符,请使用像 '[.\n]' 的模式
[...] 字符集合。匹配所包含的任意一个字符。例如, '[abc]' 可以匹配 "plain" 中的 'a'
[^...] 负值字符集合。匹配未包含的任意字符。例如, '[^abc]' 可以匹配 "plain" 中的'p'
P1|P2|P3 匹配 p1 或 p2 或 p3。例如,'z|food',能够匹配"z" 或 "food"。'(z|f)ood'则匹配 "zood" 或 "food"
* 匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等价于{0,}
+ 匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。
{n} n 是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。
{n,m} m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。
示例
<!-- 查找name字段中以'st'为开头的所有数据 -->
mysql> SELECT name FROM person_tbl WHERE name REGEXP '^st'

<!-- 查找name字段中以'ok'为结尾的所有数据 -->
mysql> SELECT name FROM person_tbl WHERE name REGEXP 'ok$'

<!-- 查找name字段中包含'mar'字符串的所有数据 -->
mysql> SELECT name FROM person_tbl WHERE name REGEXP 'mar'

<!-- 查找name字段中以元音字符开头或以'ok'字符串结尾的所有数据 -->
mysql> SELECT name FROM person_tbl WHERE name REGEXP '^[aeiou]|ok$'

MySQL的执行顺序

<!--  -->

    from →join →on →where →group by→having→select→order by→limit

<!--  -->
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349