很多开发人员在使用MySQL时经常会在部分列上进行函数计算等,导致无法走索引,在数据量大的时候,查询效率低下。针对此种情况本文从MySQL5。7及MySQL8。0中分别进行不同方式的优化。1、MySQL5。7 MySQL5。7版本中不支持函数索引,因此遇到函数索引的时候需要进行修改,否则即使查询的字段上有索引,执行时也无法使用索引而进行全表扫描,数据量大的表查询时间会比较长。具体案例如下:1。1创建测试表及数据 mysqlusetestdb;Databasechangedmysqlcreatetabletbfunction(idintprimarykeyautoincrement,namevarchar(100),createtimedatetime);QueryOK,0rowsaffected(0。01sec)mysqlinsertintotbfunction(name,creatEtime)values(anniuadaOAIFAPUHIA,2020070112:00:00);QueryOK,1rowaffected(0。02sec)mysqlinsertintotbfunction(name,creatEtime)values(CWQSsar3qcssg,2020070115:00:00);QueryOK,1rowaffected(0。01sec)mysqlinsertintotbfunction(name,creatEtime)values(vxfqrt2adafz,2020070121:30:00);QueryOK,1rowaffected(0。01sec)mysqlinsertintotbfunction(name,creatEtime)values(etxzwrwbdhegqgaheqhag,2020070201:30:00);QueryOK,1rowaffected(0。01sec)mysqlinsertintotbfunction(name,creatEtime)values(awrs433fsgvsfwtwg,2020070203:30:00);QueryOK,1rowaffected(0。00sec)mysqlinsertintotbfunction(name,creatEtime)values(awrs433fsgvsfwtwg,2020070207:32:00);QueryOK,1rowaffected(0。00sec)mysqlinsertintotbfunction(name,creatEtime)values(awrs433fsgvsfwtwg,2020070210:32:00);QueryOK,1rowaffected(0。00sec)mysqlinsertintotbfunction(name,creatEtime)values(tuilklmdadq,2020070215:32:00);QueryOK,1rowaffected(0。00sec)mysqlinsertintotbfunction(name,creatEtime)values(wesv2wqdshehq,2020070220:32:00);QueryOK,1rowaffected(0。00sec)mysqlinsertintotbfunction(name,creatEtime)values(89yoijnlkwr1,2020070302:56:00);QueryOK,1rowaffected(0。00sec)mysqlinsertintotbfunction(name,creatEtime)values(olj;nsaaq,2020070308:41:00);QueryOK,1rowaffected(0。01sec)mysqlinsertintotbfunction(name,creatEtime)values(ygo;jkdsaq,2020070316:20:00);QueryOK,1rowaffected(0。01sec)mysqlselectfromtbfunction;idnamecreatetime1anniuadaOAIFAPUHIA2020070112:00:002CWQSsar3qcssg2020070115:00:003vxfqrt2adafz2020070121:30:004etxzwrwbdhegqgaheqhag2020070201:30:005awrs433fsgvsfwtwg2020070203:30:006awrs433fsgvsfwtwg2020070207:32:007awrs433fsgvsfwtwg2020070210:32:008tuilklmdadq2020070215:32:009wesv2wqdshehq2020070220:32:001089yoijnlkwr12020070302:56:0011olj;nsaaq2020070308:41:0012ygo;jkdsaq2020070316:20:0012rowsinset(0。00sec) 1。2创建索引 在createtime字段上创建索引mysqlaltertabletbfunctionaddkeyidxcreatetime(createtime);QueryOK,0rowsaffected(0。13sec)Records:0Duplicates:0Warnings:01。3按时间查询 查询创建时间是20200701那天的所有记录 mysqlselectfromtbfunctionwheredate(createtime)20200701;idnamecreatetime1anniuadaOAIFAPUHIA2020070112:00:002CWQSsar3qcssg2020070115:00:003vxfqrt2adafz2020070121:30:003rowsinset(0。00sec) 执行计划如下: mysqlexplainselectfromtbfunctionwheredate(createtime)20200701;idselecttypetablepartitionstypepossiblekeyskeykeylenrefrowsfilteredExtra1SIMPLEtbfunctionNULLALLNULLNULLNULLNULL12100。00Usingwhere1rowinset,1warning(0。00sec) 执行计划中可以看出是进行了全面扫描1。4优化 因MySQL5。7不支持函数索引,所以需要修改SQL写法来实现走索引(或者使用虚拟列的方式),上述SQL可以修改为 mysqlselectfromtbfunctionwherecreatetime20200701andcreatetimedateadd(20200701,INTERVAL1day);idnamecreatetime1anniuadaOAIFAPUHIA2020070112:00:002CWQSsar3qcssg2020070115:00:003vxfqrt2adafz2020070121:30:003rowsinset(0。00sec) 执行计划如下: mysqlexplainselectfromtbfunctionwherecreatetime20200701andcreatetimedateadd(20200701,INTERVAL1day);idselecttypetablepartitionstypepossiblekeyskeykeylenrefrowsfilteredExtra1SIMPLEtbfunctionNULLrangeidxcreatetimeidxcreatetime6NULL3100。00Usingindexcondition1rowinset,1warning(0。00sec) 可见,修改后,使用了索引。2、MySQL8。0 MySQL8。0的索引特性增加了函数索引。其实MySQL5。7中推出了虚拟列的功能,而MySQL8。0的函数索引也是依据虚拟列来实现的。将上述的案例在MySQL8。0中实现情况如下文所述。2。1创建函数索引 在将上述的表及数据在MySQL8。0的实例上创建,然后创建createtime的函数索引,SQL如下mysqlaltertabletbfunctionaddkeyidxcreatetime((date(createtime)));注意里面字段的括号QueryOK,0rowsaffected(0。10sec)Records:0Duplicates:0Warnings:02。2按时间查询 mysqlselectfromtbfunctionwheredate(createtime)20200701;idnamecreatetime1anniuadaOAIFAPUHIA2020070112:00:002CWQSsar3qcssg2020070115:00:003vxfqrt2adafz2020070121:30:003rowsinset(0。00sec) 执行计划如下 mysqlexplainselectfromtbfunctionwheredate(createtime)20200701;idselecttypetablepartitionstypepossiblekeyskeykeylenrefrowsfilteredExtra1SIMPLEtbfunctionNULLrefidxcreatetimeidxcreatetime4const3100。00NULL1rowinset,1warning(0。00sec) 可见,在MySQL8。0创建对应的函数索引后,不改变SQL写法的前提下,查询的列上进行对应的函数计算后也可以走索引。 关于MySQL函数索引的优化及MySQL8。0函数索引还可以有更多的场景进行测试,建议大家多动手试试,提高SQL改写及优化的能力。 想了解更多内容或参与技术交流可以关注微信公众号【数据库干货铺】或进技术交流群沟通。