• mysql 学习笔记


    1 在使用多列作为主键时, 上述条件必须应用到所有列,所有列值的组合必须是唯一的(但单个列的值可以不唯一) 。
    2 多条SQL语句必须以分号(; ) 分隔。
    3 在选择多个列时, 一定要在列名之间加上逗号
    4 DISTINCT关键字作用于所有的列, 不仅仅是跟在其后的那一列
    5 返回特定数量的行:各种数据库中的这一SQL实现并不相同,sqlserver是top
    6 通常, ORDER BY子句中使用的列将是为显示而选择的列。 但是, 实际上并不一定要这样, 用非检索的列排序数据是完全合法的
    7 如果想在多个列上进行降序排序, 必须对每一列指定DESC关键字8 select name from tbl where price between 5 and 10;
    9 判断字段是否没值:SELECT "UID", "CID"    FROM "BASEINFO"."MP_SYS" where NOT "GID"  is NULL;
    10 or :在第一个条件满足时, 不管第二个条件是否满足, 相应的行都将被检索出来
    11 在where语句里可以使用圆括号: where (id=1 or id=3) and price=100
    12 IN取一组由逗号分隔、 括在圆括号中的合法值
    13 否定条件用:NOT
    14 模糊查询用 :like ,子句WHERE prod_name LIKE '%'不会匹配产品名称为NULL的行
    15 %表示任何字符出现任意次数。 下划线的用途与%一样, 但它只匹配单个字符。方括号([]) 匹配指定位置(通配符的位置) 的一个字符。
    16 别名 :
    SELECT "GID" ,"WFID" as "haha" FROM "BASEINFO"."MP_SYS" where NOT "WFID" is NULL;
    17 算术运算: + - * / ,例如
    SELECT "V01"+"V02" AS "RET" FROM "CNYB"
    18 聚合函数:avg sum max min count
    使用COUNT(*)对表中行的数目进行计数, 不管表列中包含的是空值(NULL) 还是非空值。
    使用COUNT(column)对特定列中具有值的行进行计数, 忽略NULL

    19 算术和聚合混用:
    SELECT min("P0000"+"P0015") FROM "CNYB"
    20 分组 : group by
    SELECT SUM("P1100"+"P1130"),"TYPE","ORG_ID" FROM "CNYB"."PRE_DQ_PLANT" WHERE "INDEX"=1 AND "TYPE"=1002 group by "TYPE","ORG_ID";
    除聚集计算语句外, SELECT语句中的每一列都必须在GROUP BY子句中给出

           SELECT "P1100" ,"TYPE","ORG_ID" FROM "CNYB"."PRE_DQ_PLANT" WHERE AND "INDEX"=1 AND "TYPE"=1002 group by "TYPE","ORG_ID","P1100";  -执行成功

            SELECT "P1100" ,"TYPE","ORG_ID" FROM "CNYB"."PRE_DQ_PLANT" WHERE AND "INDEX"=1 AND "TYPE"=1002 group by "TYPE","ORG_ID";  -执行失败

    21 WHERE过滤行, 而HAVING过滤分组。 WHERE在数据分组前进行过滤, HAVING在数据分组后进行过滤
    22 排序:  order by
    23 select 子句顺序: select from where group by having order by

    24 作为子查询的SELECT语句只能查询单个列。 企图检索多个列将返回错误。
    25 作为嵌套字段使用子查询:

    SELECT cust_name,cust_state,
    (SELECT COUNT(*) FROM Orders WHERE cust_id = cust_id) AS orders
    FROM Customers ORDER BY cust_name;

    26 在引用的列可能出现歧义时, 必须使用完全限定列名(用一个句点分隔表名和列名
    27 等值联结就是内联结

       等值联结:SELECT vend_name, prod_name, prod_price FROM Vendors, Products WHERE Vendors.vend_id = Products.vend_id;

       内联结: SELECT vend_name, prod_name, prod_price FROM Vendors INNER JOIN Products ON Vendors.vend_id = Products.vend_id;

    28 左联结:left outer join 全外联结:full outer join

    29 组合查询:利用union将多个select 语句的查询结果合并成一个  【UNION中的每个查询必须包含相同的列、 表达式或聚集函数

       在用UNION组合查询时, 只能使用一条ORDER BY子句, 它必须位于最后一条SELECT语句之后

       虽然ORDER BY子句似乎只是最后一条SELECT语句的组成部分, 但实际上DBMS将用它来排序所有SELECT语句返回的所有结果

    30 假如想把另一表中的顾客列合并到Customers表中,可以使用insert select  

     SELECT中列出的每一列对应于Customers表名后所跟的每一列 ,这个例子在INSERTSELECT语句中使用了相同的列名。 但是, 不一定要求列名匹配。 事实上, DBMS一点儿也不关
     心SELECT返回的列名。 它使用的是列的位置, 因此SELECT中的第一列(不管其列名) 将用来填充表列中指定的第一列, 第二列将用来填充表列中指定的第二列, 如此等等

    31 从一个表复制到另外一个表:select into  【不管从多少个表中检索数据, 数据都只能插入到一个表中 】

    32 删除:DELETE FROM Customers WHERE cust_id = '1000000006';

      更新:UPDATE Customers SET cust_email = 'kim@thetoystore.com',name="sdf" WHERE cust_id = '1000000005';
    33 DELETE删除整行而不是删除列。 要删除指定的列, 请使用UPDATE语句
    34 UPDATEDELETE语句使用WHERE子句前, 应该先用SELECT进行测试, 保证它过滤的是正确的记录, 以防编写的WHERE子句不正确。
    35 只有不允许NULL值的列可作为主键
    36 NULL值是没有值, 不是空字符串
    37 
    大多数约束是在表定义中定义的

    38 主键是唯一的, 而且永不改动,也并能为NULL,每个表只允许一个主键
    39 外键是表中的一列, 其值必须列在另一表的主键中。 外键是保证引用完整性的极其重要部分
    40 在定义外键后, DBMS不允许删除在另一个表中具有关联行的行。 例如, 不能删除关联订单的顾客。 删除该顾客的唯一方法是首先删除相关的订单
    41 取值不多的数据(如州) 不如具有更多可能值的数据(如姓或名),能通过索引得到那么多的好处




     =======索引=======

    索引匹配的最左原则具体是说,假如索引列分别为A,B,C,顺序也是A,B,C:

    • 那么查询的时候,如果查询【A】【A,B】 【A,B,C】,那么可以通过索引查询

    • 如果查询的时候,采用【A,C】,那么C这个虽然是索引,但是由于中间缺失了B,因此C这个索引是用不到的,只能用到A索引

    • 如果查询的时候,采用【B】 【B,C】 【C】,由于没有用到第一列索引,不是最左前缀,那么后面的索引也是用不到了

    • 如果查询的时候,采用范围查询,并且是最左前缀,也就是第一列索引,那么可以用到索引,但是范围后面的列无法用到索引

    因为索引虽然加快了查询速度,但索引也是有代价的:索引文件本身要消耗存储空间,同时索引会加重插入、删除和修改记录时的负担,另外,MySQL在运行时也要消耗资源维护索引,因此索引并不是越多越好

    请尽量在InnoDB上采用自增字段做主键。

    建立索引的常用技巧

    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)的索引,那么只需要修改原来的索引即可,当然要考虑原有数据和线上使用情况

    我们常常用到explain这个命令来查看一个这些SQL语句的执行计划,查看该SQL语句有没有使用上了索引,有没有做全表扫描

    ==========

    强制使用索引:
    select * from acct_trans_log force index(idx_acct_id)
    WHERE acct_id = 1000000000009000757
    order by create_time desc limit 0,10

    ==========

    在建立了联合索引idx_acct_id_create_time的情况下

    快:select * from acct_trans_log WHERE  acct_id = 3095 order by create_time

    慢:select * from acct_trans_log force index(idx_acct_id_create_time) WHERE  acct_id in(3095,1000000000009000757) order by create_time desc limit 0,10

    问题出在了排序 上,查询结果集排序如下:

    id1+time1

    id1+time2

    id1+time3

    id2+time1

    id2+time2

    id2+time3

     索引出来的默认排序是这样的,id是有序的,时间是无序的,因为有2个id,优先按id排序,时间就是乱的了。

    若只查询id1或id2,默认顺序已经排好了,所以会很快,所以将in改成union all 会变快

    =========

    使用explain 只需要在原有select 基础上加上explain关键字就可以了,如下:explain select * from servers;

    explain各个字段的含义

    table:显示这一行数据是关于哪张表的
    type:显示使用了何种类型,从最好到最差的连接类型为const,eq_ref,ref,range,index,all
    possible_keys:显示可能应用在这张表中的索引。如果为空,没有可能的索引
    key:实际使用的索引,如果为null,则没有使用索引。
    key_len:使用的索引的长度。在不损失精确性的情况下,长度越短越好
    ref:显示索引的哪一列被使用了,如果可能的话,是一个常数
    rows:mysql认为必须检查的用来返回请求数据的行数
    id : 表示SQL执行的顺序的标识,SQL从大到小的执行
    
    select_type:表示查询中每个select子句的类型
    
    table:显示这一行的数据是关于哪张表的,有时不是真实的表名字
    
    type:表示MySQL在表中找到所需行的方式,又称“访问类型”。常用的类型有:ALL, index, range, ref, eq_ref, const, system, NULL(从左到右,性能从差到好)
    
    possible_keys:指出MySQL能使用哪个索引在表中找到记录,查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询使用
    
    Key:key列显示MySQL实际决定使用的键(索引),如果没有选择索引,键是NULL。
    
    key_len:表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度(key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的)
    
    ref:表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值
    
    rows:表示MySQL根据表统计信息及索引选用情况,估算的找到所需的记录所需要读取的行数,理论上行数越少,查询性能越好
    
    Extra:该列包含MySQL解决查询的详细信息
    • EXPLAIN不会告诉你关于触发器、存储过程的信息或用户自定义函数对查询的影响情况

    • EXPLAIN不考虑各种Cache

    • EXPLAIN不能显示MySQL在执行查询时所作的优化工作

    • 部分统计信息是估算的,并非精确值

    • EXPALIN只能解释SELECT操作,其他操作要重写为SELECT后查看执行计划。

    mysql> explain select msg_id from circlemessage_idx_0 where  to_id = 113487 and circle_id=10019063  and msg_id>=6273803462253938690  and from_id != 113487 order by msg_id asc limit 30;
    +----+-------------+---------------------+-------+-------------------------+---------+---------+------+--------+-------------+
    | id | select_type | table               | type  | possible_keys           | key     | key_len | ref  | rows   | Extra       |
    +----+-------------+---------------------+-------+-------------------------+---------+---------+------+--------+-------------+
    |  1 | SIMPLE      | circlemessage_idx_0 | range | PRIMARY,idx_from_circle | PRIMARY | 16      | NULL | 349780 | Using where |
    +----+-------------+---------------------+-------+-------------------------+---------+---------+------+--------+-------------+
    1 row in set (0.00 sec)
    mysql> explain select msg_id from circlemessage_idx_0 where  to_id = 113487 and circle_id=10019063   and from_id != 113487 order by msg_id asc limit 30;
    +----+-------------+---------------------+-------+-----------------+---------+---------+------+------+-------------+
    | id | select_type | table               | type  | possible_keys   | key     | key_len | ref  | rows | Extra       |
    +----+-------------+---------------------+-------+-----------------+---------+---------+------+------+-------------+
    |  1 | SIMPLE      | circlemessage_idx_0 | index | idx_from_circle | PRIMARY | 16      | NULL |   30 | Using where |
    +----+-------------+---------------------+-------+-----------------+---------+---------+------+------+-------------+
    1 row in set (0.00 sec)

    通过上面两个执行计划可以发现当没有msg_id >= xxx这个查询条件的时候,检索的rows要少很多,并且两者查询的时候都用到了索引,而且用到的还只是主键索引。那说明索引应该是不合理的,没有发挥最大作用。

    分析这个执行计划可以看到,当包含msg_id >= xxx 查询条件的时候,rows有34w多行,这种情况,说明检索太多,要么就是表里面确实有这么大,要么就是索引不合理没有用到索引,大都情况是没用合理用到索引。列中所用到的索引也是PRIMARY,那就可能是(msg_id,to_id)的其中一个,注意我们建立表的时候msg_id索引的顺序是在to_id前面的,因此MySQL查询一定会优先用msg_id索引,在使用了msg_id索引后,就已经检索出了34w行,并且由于msg_id的查询条件是大于等于,因此,再这个查询条件后,就不能再用到to_id的索引

    然后再看key_len长度为16,结合 key为PRIMARY,那么可以分析得知,只有一个主键索引被用到。

    最后看看 type 值,是range,那么就说明这个查询要么是范围查询,要么就是多值匹配

    请注意,from_id != xxx这样的语句,是无法用到索引的。只有from_id = xxx就可以用到所以,因此from id 的索引其实可以不用,建立索引的时候就要考虑清楚

  • 相关阅读:
    【死磕Java并发】—–J.U.C之AQS(一篇就够了)
    Java并发包基石-AQS详解
    java并发api总结
    用Java对CSV文件进行读写操作
    多线程批量检测未注册域名
    RSA公钥、私钥、签名和验签
    ASCII,Unicode和UTF-8终于找到一个能完全搞清楚的文章了
    Java 常用工具类---- 各种字符集编码判断与转换
    JavaMail| JavaMail配置属性
    QT下的几种透明效果(QPalette背景白色,窗口设置setWindowOpacity,QPainter使用Clear模式绘图)
  • 原文地址:https://www.cnblogs.com/testzcy/p/11493613.html
Copyright © 2020-2023  润新知