count(* )、count(id)、count(1)

  • MyISAM
    将总数存在磁盘上,直接读取。(没有where 条件的)
  • InnoDB
    需要读出数据累加

    show table status 中的TABLE_ROWS 使用的是 采样估算出的数量。
    优化器针对count(* )有特殊优化。
    SQL优化 - 图1

  • count(字段):判断null【null值不算】,读字段,累加

  • count(主键):读主键,累加
  • count(1):数1
  • count( ):*不取值,按行累加(返回索引树中数据的个数)

    FIND_IN_SET:判断字段包含

    SQL优化 - 图2 SELECT id,name,list from tb_test WHERE FIND_IN_SET(‘daodao’,list);

使用MYSQL查询数据表中某个字段包含某个数值_三生石的博客-CSDN博客_mysql查询包含某一字符串的值

【坑】not in 处理null的坑,并且not in不走索引

MySQL NOT IN的坑——注意null - 简书
原因是not in的实现原理是,对每一个table1.name和每一个table2.name(括号内的查询结果)进行不相等比较(!=)【所以不走索引】

  1. foreach name in table2:
  2. if table1.name != name:
  3. continue
  4. else:
  5. return false
  6. return true

而sql中任意!=null的运算结果都是false(!=null返回null)所以如果table2中存在一个null,not in的查询永远都会返回false,即查询结果为空。
正确做法:要将null在子查询中过滤掉。
image.png

is not null 和 !=null区别

image.png
只用 is、is not就行了。

解决is not null不走索引 & !=不走索引

x is not null
变为 x>0

x !=20
变为 x<20 and x>20

UNION ALL操作符替代UNION

union all 没有去重语义,不需要临时表。UNION需要临时表

随机取n个

image.png
image.png

大分页优化

子查询优化(索引覆盖)

  1. SELECT id, value, LENGTH(stuffing) AS len
  2. FROM t_limit
  3. ORDER BY
  4. id
  5. LIMIT 150000, 10

优化后

  1. SELECT l.id, value, LENGTH(stuffing) AS len
  2. FROM (
  3. SELECT id
  4. FROM t_limit
  5. ORDER BY
  6. id
  7. LIMIT 150000, 10
  8. ) o
  9. JOIN t_limit l
  10. ON l.id = o.id
  11. ORDER BY
  12. l.id

因为Mysql总是early row lookup【遍历id每一步都读取整行的内容】,
因为使用的select * ?
不知道mysql为什么不做优化?哪里不好优化么?有人有相同的质疑:

每个商品各个供应商中的最高价(nice)

  1. SELECT s1.article, s1.dealer, s1.price
  2. FROM shop s1
  3. LEFT JOIN shop s2 ON s1.article = s2.article AND s1.price < s2.price
  4. WHERE s2.article IS NULL ORDER BY s1.article;

max min优化

  • 针对全部数据max 和 min 有缓存结果,可直接获取。
  • 针对条件查询max min,代替max函数,可以在索引字段使用 order by limit 1 方式返回最大最小值。

MySQL之查询:max()和min()函数与索引利用_u012393450的博客-CSDN博客

磁盘io高问题

原因

  1. 写大量日志
  2. 大批量写数据
  3. 产生大量磁盘临时表

    查看磁盘临时表数量方法

    lsof查看mysql进程产生的磁盘临时表

    image.png

    status ‘%tmp%’查看临时表数量

    image.png

    避免产生磁盘临时表

    image.png

select需要加事务么?

mysql 查询需不需要加事务? - 知乎
多个select 放在一个事务里,会变成大事务影响效率。
但是
只读事务 @Transactional(readOnly = true) 貌似有又优化?
例如Oracle对于只读事务,不启动回滚段,不记录回滚log。

统计每一行记录的平均大小

image.png
image.png
length()方法只能计算字符串类型。

求行号

方法一:
image.png
方法二:
image.png