mysql 定位数据的办法:rowid

每个引擎用来唯一标识数据行的信息。

  • 有主键的InnoDB表,rowid就是主键id
  • 没有主键的InnoDB表,rowid由系统自己生成一个长度为6字节的rowid

order by rand()

通过expain可以发现,order by rand()会使用内存临时表,内存临时表排序时使用了rowid排序。结论:order by rand()的计算过程非常复杂,需要大量的扫描行数,排序过程耗费的资源也很大。
image.png
对于内存表临时表,回表过程只是简单地根据数据行的位置,直接访问内存得到数据,不会导致磁盘访问。内存临时表的大小可以通过参数tmp_table_size来控制,默认大小是16M,超过tmp_table_size的内存临时表就会转为磁盘临时表。
磁盘临时表的默认引擎是InnoDB,由参数internal_tmp_disk_storage_engine控制。

用计算代替order by rand()

  • 取得整个表的行数C
  • 用floor(C*rand())=Y,来作为随机行数值
  • 用limitY,1取得随机一行

这种办法的扫,描行数为C+Y+1行,极短考虑最大行数是总行数的2倍。但是由于limitY,1的排序是使用的已有序的主键,不用临时表,所以代价小很多。