MySQL 函數(shù)索引的優(yōu)化方案
很多開發(fā)人員在使用MySQL時經(jīng)常會在部分列上進(jìn)行函數(shù)計算等,導(dǎo)致無法走索引,在數(shù)據(jù)量大的時候,查詢效率低下。針對此種情況本文從MySQL5.7 及MySQL8.0中分別進(jìn)行不同方式的優(yōu)化。
1、 MySQL5.7
MySQL5.7版本中不支持函數(shù)索引,因此 遇到函數(shù)索引的時候需要進(jìn)行修改,否則即使查詢的字段上有索引,執(zhí)行時也無法使用索引而進(jìn)行全表掃描,數(shù)據(jù)量大的表查詢時間會比較長。具體案例如下:
1.1 創(chuàng)建測試表及數(shù)據(jù)
mysql> use testdb; Database changed mysql> create table tb_function(id int primary key auto_increment,name varchar(100),create_time datetime); Query OK, 0 rows affected (0.01 sec) mysql> insert into tb_function(name,creatE_time) values('anniuadaOAIFAPUHIA','2020-07-01 12:00:00'); Query OK, 1 row affected (0.02 sec) mysql> insert into tb_function(name,creatE_time) values('CWQSsar3qcssg','2020-07-01 15:00:00'); Query OK, 1 row affected (0.01 sec) mysql> insert into tb_function(name,creatE_time) values('vxfqrt2adafz','2020-07-01 21:30:00'); Query OK, 1 row affected (0.01 sec) mysql> insert into tb_function(name,creatE_time) values('etxzwrwbdhegqgaheqhag','2020-07-02 01:30:00'); Query OK, 1 row affected (0.01 sec) mysql> insert into tb_function(name,creatE_time) values('awrs433fsgvsfwtwg','2020-07-02 03:30:00'); Query OK, 1 row affected (0.00 sec) mysql> insert into tb_function(name,creatE_time) values('awrs433fsgvsfwtwg','2020-07-02 07:32:00'); Query OK, 1 row affected (0.00 sec) mysql> insert into tb_function(name,creatE_time) values('awrs433fsgvsfwtwg','2020-07-02 10:32:00'); Query OK, 1 row affected (0.00 sec) mysql> insert into tb_function(name,creatE_time) values('tuilklmdadq','2020-07-02 15:32:00'); Query OK, 1 row affected (0.00 sec) mysql> insert into tb_function(name,creatE_time) values('wesv2wqdshehq','2020-07-02 20:32:00'); Query OK, 1 row affected (0.00 sec) mysql> insert into tb_function(name,creatE_time) values('89yoijnlkwr1','2020-07-03 02:56:00'); Query OK, 1 row affected (0.00 sec) mysql> insert into tb_function(name,creatE_time) values('olj;nsaaq','2020-07-03 08:41:00'); Query OK, 1 row affected (0.01 sec) mysql> insert into tb_function(name,creatE_time) values('ygo;jkdsaq','2020-07-03 16:20:00'); Query OK, 1 row affected (0.01 sec) mysql> select * from tb_function; +----+-----------------------+---------------------+ | id | name | create_time | +----+-----------------------+---------------------+ | 1 | anniuadaOAIFAPUHIA | 2020-07-01 12:00:00 | | 2 | CWQSsar3qcssg | 2020-07-01 15:00:00 | | 3 | vxfqrt2adafz | 2020-07-01 21:30:00 | | 4 | etxzwrwbdhegqgaheqhag | 2020-07-02 01:30:00 | | 5 | awrs433fsgvsfwtwg | 2020-07-02 03:30:00 | | 6 | awrs433fsgvsfwtwg | 2020-07-02 07:32:00 | | 7 | awrs433fsgvsfwtwg | 2020-07-02 10:32:00 | | 8 | tuilklmdadq | 2020-07-02 15:32:00 | | 9 | wesv2wqdshehq | 2020-07-02 20:32:00 | | 10 | 89yoijnlkwr1 | 2020-07-03 02:56:00 | | 11 | olj;nsaaq | 2020-07-03 08:41:00 | | 12 | ygo;jkdsaq | 2020-07-03 16:20:00 | +----+-----------------------+---------------------+ 12 rows in set (0.00 sec)
1.2 創(chuàng)建索引
在create_time字段上創(chuàng)建索引
mysql> alter table tb_function add key idx_create_time(create_time); Query OK, 0 rows affected (0.13 sec) Records: 0 Duplicates: 0 Warnings: 0
1.3 按時間查詢
查詢創(chuàng)建時間是2020-07-01那天的所有記錄
mysql> select * from tb_function where date(create_time)='2020-07-01'; +----+--------------------+---------------------+ | id | name | create_time | +----+--------------------+---------------------+ | 1 | anniuadaOAIFAPUHIA | 2020-07-01 12:00:00 | | 2 | CWQSsar3qcssg | 2020-07-01 15:00:00 | | 3 | vxfqrt2adafz | 2020-07-01 21:30:00 | +----+--------------------+---------------------+ 3 rows in set (0.00 sec)
執(zhí)行計劃如下:
mysql> explain select * from tb_function where date(create_time)='2020-07-01'; +----+-------------+-------------+------------+------+---------------+------+---------+------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------------+------------+------+---------------+------+---------+------+------+----------+-------------+ | 1 | SIMPLE | tb_function | NULL | ALL | NULL | NULL | NULL | NULL | 12 | 100.00 | Using where | +----+-------------+-------------+------------+------+---------------+------+---------+------+------+----------+-------------+ 1 row in set, 1 warning (0.00 sec)
執(zhí)行計劃中可以看出是進(jìn)行了全面掃描
1.4 優(yōu)化
因MySQL5.7不支持函數(shù)索引,所以需要修改SQL寫法來實現(xiàn)走索引(或者使用虛擬列的方式),上述SQL可以修改為
mysql> select * from tb_function where create_time>='2020-07-01' and create_time<date_add('2020-07-01',INTERVAL 1 day); +----+--------------------+---------------------+ | id | name | create_time | +----+--------------------+---------------------+ | 1 | anniuadaOAIFAPUHIA | 2020-07-01 12:00:00 | | 2 | CWQSsar3qcssg | 2020-07-01 15:00:00 | | 3 | vxfqrt2adafz | 2020-07-01 21:30:00 | +----+--------------------+---------------------+ 3 rows in set (0.00 sec)
執(zhí)行計劃如下:
mysql> explain select * from tb_function where create_time>='2020-07-01' and create_time<date_add('2020-07-01',INTERVAL 1 day); +----+-------------+-------------+------------+-------+-----------------+-----------------+---------+------+------+----------+-----------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------------+------------+-------+-----------------+-----------------+---------+------+------+----------+-----------------------+ | 1 | SIMPLE | tb_function | NULL | range | idx_create_time | idx_create_time | 6 | NULL | 3 | 100.00 | Using index condition | +----+-------------+-------------+------------+-------+-----------------+-----------------+---------+------+------+----------+-----------------------+ 1 row in set, 1 warning (0.00 sec)
可見,修改后,使用了索引。
2、MySQL8.0
MySQL8.0的索引特性增加了函數(shù)索引。其實MySQL5.7中推出了虛擬列的功能,而MySQL8.0的函數(shù)索引也是依據(jù)虛擬列來實現(xiàn)的。將上述的案例在MySQL8.0中實現(xiàn)情況如下文所述。
2.1 創(chuàng)建函數(shù)索引
在將上述的表及數(shù)據(jù)在MySQL8.0的實例上創(chuàng)建,然后創(chuàng)建create_time的函數(shù)索引,SQL如下
mysql> alter table tb_function add key idx_create_time((date(create_time))); -- 注意里面字段的括號 Query OK, 0 rows affected (0.10 sec) Records: 0 Duplicates: 0 Warnings: 0
2.2 按時間查詢
mysql> select * from tb_function where date(create_time)='2020-07-01'; +----+--------------------+---------------------+ | id | name | create_time | +----+--------------------+---------------------+ | 1 | anniuadaOAIFAPUHIA | 2020-07-01 12:00:00 | | 2 | CWQSsar3qcssg | 2020-07-01 15:00:00 | | 3 | vxfqrt2adafz | 2020-07-01 21:30:00 | +----+--------------------+---------------------+ 3 rows in set (0.00 sec)
執(zhí)行計劃如下
mysql> explain select * from tb_function where date(create_time)='2020-07-01'; +----+-------------+-------------+------------+------+-----------------+-----------------+---------+-------+------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------------+------------+------+-----------------+-----------------+---------+-------+------+----------+-------+ | 1 | SIMPLE | tb_function | NULL | ref | idx_create_time | idx_create_time | 4 | const | 3 | 100.00 | NULL | +----+-------------+-------------+------------+------+-----------------+-----------------+---------+-------+------+----------+-------+ 1 row in set, 1 warning (0.00 sec)
可見,在MySQL8.0 創(chuàng)建對應(yīng)的函數(shù)索引后,不改變SQL寫法的前提下,查詢的列上進(jìn)行對應(yīng)的函數(shù)計算后也可以走索引。
關(guān)于MySQL函數(shù)索引的優(yōu)化及MySQL8.0函數(shù)索引還可以有更多的場景進(jìn)行測試,建議大家多動手試試,提高SQL改寫及優(yōu)化的能力。
以上就是MySQL 函數(shù)索引的優(yōu)化方案的詳細(xì)內(nèi)容,更多關(guān)于MySQL 函數(shù)索引及優(yōu)化方案的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
pymysql.err.DataError:(1264, ")異常的有效解決方法(最新推薦)
遇到pymysql.err.DataError錯誤時,錯誤代碼1264通常指的是MySQL數(shù)據(jù)庫中的Out of range value for column錯誤,這意味著你嘗試插入或更新的數(shù)據(jù)超過了對應(yīng)數(shù)據(jù)庫列所允許的范圍,這篇文章主要介紹了pymysql.err.DataError:(1264, ")異常的有效問題,需要的朋友可以參考下2024-05-05mysql數(shù)據(jù)庫操作_高手進(jìn)階常用的sql命令語句大全
mysql數(shù)據(jù)庫操作sql命令語句大全:三表連表查詢、更新時批量替換字段部分字符、判斷某一張表是否存在、自動增長恢復(fù)從1開始、查詢重復(fù)記錄、更新時字段值等于原值加上一個字符串、更新某字段為隨機(jī)值、復(fù)制表數(shù)據(jù)到另一個表、創(chuàng)建表時拷貝其他表的數(shù)據(jù)和結(jié)構(gòu)...2022-11-11關(guān)于MySQL innodb_autoinc_lock_mode介紹
下面小編就為大家?guī)硪黄P(guān)于MySQL innodb_autoinc_lock_mode介紹。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-03-03連接mysql報錯——沒有設(shè)置“usessl=false”的問題
這篇文章主要介紹了連接mysql報錯——沒有設(shè)置“usessl=false”的問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-08-08