欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解隱秘的?MySQL?類型轉(zhuǎn)換問(wèn)題詳解

 更新時(shí)間:2022年10月14日 09:50:52   作者:架構(gòu)精進(jìn)之路  
這篇文章主要為大家介紹了詳解隱秘的?MySQL?類型轉(zhuǎn)換問(wèn)題詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

1、問(wèn)題開(kāi)篇

本文來(lái)自于我近期工作中遇到的一個(gè)真實(shí)問(wèn)題,稍作整理后分享給大家~

一張用戶表,其中 phone 添加了普通索引:

CREATE TABLE users (
	id bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
	name varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '名稱',
	phone varchar(16) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '手機(jī)',
	created_at timestamp NOT NULL DEFAULT '1970-01-01 16:00:00' COMMENT '創(chuàng)建時(shí)間',
	updated_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新時(shí)間',
	PRIMARY KEY (id),
	KEY idx_phone (phone)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用戶表';

分別執(zhí)行以下 SQL:

1、字符串類型查詢

EXPLAIN SELECT * FROM users WHERE phone = '2';

執(zhí)行計(jì)劃如下:

2、數(shù)值型查詢

EXPLAIN SELECT * FROM users WHERE phone = 2;

執(zhí)行計(jì)劃如下:

發(fā)現(xiàn)問(wèn)題:

當(dāng)索引字段 `phone` 為字符串類型時(shí),字符串查詢時(shí)候使用了索引`idx_phone`,而數(shù)值類型查詢時(shí)候竟無(wú)法使用索引`idx_phone`。

2、問(wèn)題引申

假如索引字段為整型的話,那用字符串查詢時(shí)會(huì)不會(huì)走索引呢?

實(shí)踐出真知,我們來(lái)驗(yàn)證一下。

同樣如上表,修改字段 `phone` 類型由 varchar 變更為 bigint:

ALTER TABLE users MODIFY COLUMN phone bigint(16) NOT NULL COMMENT '手機(jī)';

然后,分別執(zhí)行以下 SQL:

1、字符串類型查詢

EXPLAIN SELECT * FROM users WHERE phone = '2';

執(zhí)行計(jì)劃如下:

2、數(shù)值型查詢

EXPLAIN SELECT * FROM users WHERE phone = 2;

執(zhí)行計(jì)劃如下:

執(zhí)行后發(fā)現(xiàn),無(wú)論是以字符串查詢還是以數(shù)值型查詢都會(huì)用到索引。

小結(jié):

  • 當(dāng)索引字段是數(shù)值類型時(shí),數(shù)值型或者字符型查詢都不影響索引的使用。
  • 當(dāng)索引字段是字符類型時(shí),數(shù)值型查詢無(wú)法使用索引,字符型查詢可正常使用索引。

3、跟進(jìn)探究

為什么會(huì)是這樣呢?其根源就是 MySQL 的隱式類型轉(zhuǎn)換。

3.1 什么是隱式類型轉(zhuǎn)換?

在 MySQL 中,當(dāng)操作符與不同類型的操作數(shù)一起使用時(shí),會(huì)發(fā)生類型轉(zhuǎn)換以使操作數(shù)兼容,則會(huì)發(fā)生隱式類型轉(zhuǎn)換。

即 MySQL 會(huì)根據(jù)需要自動(dòng)將數(shù)字轉(zhuǎn)換為字符串,或者將字符串轉(zhuǎn)換為數(shù)字。

mysql> SELECT 1+'1';
-> 2
mysql> SELECT CONCAT(2,' test');
-> '2 test'

很明顯,上面的 SQL 語(yǔ)句的執(zhí)行過(guò)程中就出現(xiàn)了隱式轉(zhuǎn)化。

從結(jié)果我們可以判定,SQL1 中將字符串的“1”轉(zhuǎn)換為數(shù)字 1,而在 SQL2 中,將數(shù)字 2 轉(zhuǎn)換為字符串“2”。

3.2 如何避免隱式類型轉(zhuǎn)換?

3.2.1 清楚轉(zhuǎn)換規(guī)則

只有當(dāng)清楚的知道隱式類型轉(zhuǎn)換的規(guī)則,才能從根本上避免產(chǎn)生隱式類型轉(zhuǎn)換。

參考 MySQL 文檔相關(guān)描述,確定隱式類型轉(zhuǎn)換規(guī)則:

1、兩個(gè)參數(shù)至少有一個(gè)是 NULL 時(shí),比較的結(jié)果也是 NULL,例外是使用 <=> 對(duì)兩個(gè) NULL 做比較時(shí)會(huì)返回 1,這兩種情況都不需要做類型轉(zhuǎn)換

2、兩個(gè)參數(shù)都是字符串,會(huì)按照字符串來(lái)比較,不做類型轉(zhuǎn)換

3、兩個(gè)參數(shù)都是整數(shù),按照整數(shù)來(lái)比較,不做類型轉(zhuǎn)換

4、十六進(jìn)制的值和非數(shù)字做比較時(shí),會(huì)被當(dāng)做二進(jìn)制串

5、有一個(gè)參數(shù)是 TIMESTAMP 或 DATETIME,并且另外一個(gè)參數(shù)是常量,常量會(huì)被轉(zhuǎn)換為 timestamp

6、有一個(gè)參數(shù)是 decimal 類型,如果另外一個(gè)參數(shù)是 decimal 或者整數(shù),會(huì)將整數(shù)轉(zhuǎn)換為 decimal 后進(jìn)行比較,如果另外一個(gè)參數(shù)是浮點(diǎn)數(shù),則會(huì)把 decimal 轉(zhuǎn)換為浮點(diǎn)數(shù)進(jìn)行比較

7、所有其他情況下,兩個(gè)參數(shù)都會(huì)被轉(zhuǎn)換為浮點(diǎn)數(shù)再進(jìn)行比較

驗(yàn)證示例:

mysql> SELECT 'aa' + 1;
-> '1'
mysql> show warnings;
+---------+------+----------------------------------------+
| Level   | Code | Message                                |
+---------+------+----------------------------------------+
| Warning | 1292 | Truncated incorrect DOUBLE value: 'aa' |
+---------+------+----------------------------------------+

上述示例中,將字符串 'aa' 和 1 進(jìn)行求和,因?yàn)?'aa' 和數(shù)字 1 的類型不同,通過(guò)上述轉(zhuǎn)換規(guī)則并且經(jīng)查看 warnings 可以確認(rèn):隱式類型轉(zhuǎn)化將字符串轉(zhuǎn)為了 double 類型。

由于字符串是非數(shù)字型的,所以就會(huì)被轉(zhuǎn)換為 0,因此計(jì)算結(jié)果:0+1=1

3.2.2 使用內(nèi)置函數(shù)顯示轉(zhuǎn)換

MySQL 對(duì)數(shù)據(jù)進(jìn)行類型轉(zhuǎn)換,提供了 cast() 和 convert()。

相同點(diǎn):兩者都是進(jìn)行數(shù)據(jù)類型轉(zhuǎn)換,實(shí)現(xiàn)的功能基本等同

不同點(diǎn):兩者的語(yǔ)法不同:cast(value as type) 、 convert(value,type)

將數(shù)值型轉(zhuǎn)換為字符串型,應(yīng)用示例如下:

mysql> SELECT CAST(123 as char);
-> '123'
mysql> SELECT CONVERT(123, char);
-> '123'

假如應(yīng)用在開(kāi)篇描述問(wèn)題的查詢中,則如下所示:

EXPLAIN SELECT * FROM users WHERE phone = CAST(123 AS CHAR);

結(jié)果所示:

結(jié)果顯示同應(yīng)用字符串類型參數(shù)一樣,可使用索引`idx_phone`。

3.2.3 類型保持一致

最簡(jiǎn)單的一種,保證查詢應(yīng)用規(guī)范,SQL 參數(shù)類型與數(shù)據(jù)庫(kù)中字段類型保持一致即可。

3.3 字符類型轉(zhuǎn)換

另外,關(guān)于字符串類型轉(zhuǎn)換的一些補(bǔ)充:

mysql> select '1a2b3c' = 1;
-> 1
mysql> select 'a1b2c3' = 0;
-> 1

從上面的例子可以得出:

  • 如果字符串的第一個(gè)字符就是非數(shù)字的字符,那么轉(zhuǎn)換為數(shù)字就是 0;
  • 如果字符串以數(shù)字開(kāi)頭,那轉(zhuǎn)換的數(shù)字就是開(kāi)頭的那些數(shù)字對(duì)應(yīng)的值,直到遇到非數(shù)字字符才結(jié)束。

4、總結(jié)

本文主要從問(wèn)題入手,繼而進(jìn)行問(wèn)題引申,最終挖掘出問(wèn)題根源:MySQL 隱式類型轉(zhuǎn)換。

同時(shí)也告誡我們?nèi)粘T趯?xiě) SQL 時(shí)一定要檢查參數(shù)類型與數(shù)據(jù)庫(kù)字段類型是否一致,否則可能造成隱式類型轉(zhuǎn)換,不能正常應(yīng)用索引,造成慢查詢,甚至拖垮整個(gè)數(shù)據(jù)庫(kù)服務(wù)集群。

如果參數(shù)不一致,也可以考慮使用 CAST 函數(shù)顯性轉(zhuǎn)換成一致類型。

數(shù)據(jù)表設(shè)計(jì)及應(yīng)用絕非易事,需要考慮的因素太多了,大家應(yīng)用過(guò)程注意保持敬畏心。

以上就是詳解隱秘的 MySQL 類型轉(zhuǎn)換問(wèn)題詳解的詳細(xì)內(nèi)容,更多關(guān)于MySQL 類型轉(zhuǎn)換的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • MLSQL Stack如何讓流調(diào)試更加簡(jiǎn)單詳解

    MLSQL Stack如何讓流調(diào)試更加簡(jiǎn)單詳解

    這篇文章主要給大家介紹了關(guān)于MLSQL Stack如何讓流調(diào)試更加簡(jiǎn)單的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用MLSQL具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06
  • mysql?sock?文件解析及作用講解

    mysql?sock?文件解析及作用講解

    這篇文章主要為大家介紹了mysql.sock?文件解析及作用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • MySQL Like模糊查詢速度太慢如何解決

    MySQL Like模糊查詢速度太慢如何解決

    這篇文章主要介紹了MySQL Like模糊查詢速度太慢如何解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-10-10
  • MySQL索引操作命令小結(jié)

    MySQL索引操作命令小結(jié)

    這篇文章主要介紹了MySQL索引操作命令小結(jié),本文講解了創(chuàng)建索引、查詢索引、刪除索引等內(nèi)容,需要的朋友可以參考下
    2014-12-12
  • CentOS6.8使用cmake安裝MySQL5.7.18

    CentOS6.8使用cmake安裝MySQL5.7.18

    這篇文章主要為大家詳細(xì)介紹了CentOS6.8使用cmake安裝MySQL5.7.18的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • mysql主鍵id的生成方式(自增、唯一不規(guī)則)

    mysql主鍵id的生成方式(自增、唯一不規(guī)則)

    本文主要介紹了mysql主鍵id的生成方式,主要包括兩種生成方式,文中通過(guò)代碼示例介紹的非常詳細(xì),感興趣的可以了解一下
    2021-09-09
  • 淺談MySQL中的六種日志

    淺談MySQL中的六種日志

    MySQL中存在著6種日志,本文是對(duì)MySQL日志文件的概念及基本使用介紹,不涉及底層內(nèi)容,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • MySQL中DATEDIFF()函數(shù)用法及返回周、月、年

    MySQL中DATEDIFF()函數(shù)用法及返回周、月、年

    這篇文章主要給大家介紹了關(guān)于MySQL中DATEDIFF()函數(shù)用法及返回周、月、年的相關(guān)資料,datediff()函數(shù)返回兩個(gè)日期之間的時(shí)間,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2023-11-11
  • MySQL批量導(dǎo)入Excel數(shù)據(jù)(超詳細(xì))

    MySQL批量導(dǎo)入Excel數(shù)據(jù)(超詳細(xì))

    這篇文章主要介紹了MySQL批量導(dǎo)入Excel數(shù)據(jù)(超詳細(xì)),文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,感興趣的小伙伴可以參考一下,希望對(duì)你的學(xué)習(xí)有所幫助
    2022-08-08
  • MYSQL索引建立需要注意以下幾點(diǎn)細(xì)節(jié)

    MYSQL索引建立需要注意以下幾點(diǎn)細(xì)節(jié)

    建立MYSQL索引時(shí)需要注意以下幾點(diǎn):建立索引的時(shí)機(jī)/對(duì)于like/對(duì)于有多個(gè)條件的/開(kāi)啟索引緩存/建立索引是有代價(jià)的等等,感興趣的你可以參考下本文,或許可以幫助到你
    2013-03-03

最新評(píng)論