MySQL INNODB零碎知識點

1. MySQL repair, optimize, analyze

(1)REPAIR TABLE table_name; (修復被損壞的表,能修復MYISAM索引的表,不能直接修復INNODB、MEMORY等索引表)

修復步驟:

首先CHECK TABLE table_name;檢查是否發生了表損壞

如果表損壞可以使用REPAIR TABLE table_name;直接修復MYISAM索引表。

如果是INNODB索引表可以使用一下方式:

先將數據導出一份

ALTER TABLE table_name ENGINE=INNODB;

將數據重新導入

(2)OPTIMIZE TABLE table_name; (回收閒置的數據庫空間、減少數據碎片,能整理MYISAM索引的表,不能直接整理INNODB、MEMORY等索引表)

整理步驟:

如果是INNODB索引表可以使用一下方式:

先將數據導出一份

ALTER TABLE table_name ENGINE=INNODB;

將數據重新導入

或者

ALTER TABLE table_name ENGINE=InnoDB;

ANALYZE TABLE table_name ;

(3)ANALYZE TABLE table_name; (更新統計信息,其主要目的就是解決查詢查詢計劃不穩定的情況。SHOW INDEX FROM table_name;和SHOW TABLE STATUS;也會觸發統計信息的更新)

SHOW INDEX FROM table_name;中的信息取自information_schema.`STATISTICS`表。

2. MySQL如何查看優化器優化後的SQL

(1) MySQL8.0:

EXPLAIN sql語句;

SHOW WARNINGS;  -- 可以查看到優化後的sql語句

(2) MySQL8.0之前版本:

EXPLAIN EXTENDED sql語句;

SHOW WARNINGS;  -- 可以查看到優化後的sql語句

3. 優化器會將in(子查詢)優化成join的形式

例如:

EXPLAIN SELECT film.`title` FROM sakila.film WHERE film_id IN (SELECT film_id FROM sakila.`film_actor` WHERE actor_id=1);

SHOW WARNINGS
           /* select#1 */ SELECT `sakila`.`film`.`title` AS `title` FROM `sakila`.`film_actor` JOIN `sakila`.`film` WHERE ((`sakila`.`film`.`film_id` = `sakila`.`film_actor`.`film_id`) AND (`sakila`.`film_actor`.`actor_id` = 1))

4. 如何用sum()和count()統計某具體一列的數量

例如:(統計first_name=‘ED’列的總數量)

SELECT COUNT(first_name='ED' OR NULL) FROM sakila.actor;  -- count在統計列時只會統計非NULL的列,並不會判定是否滿足表達式

SELECT SUM(first_name='ED') FROM sakila.actor;

5. SQL語句的語法順序和執行順序

語法順序:

select[distinct],from,join(如left join),on,where,group by,having,union,order by,limit。

執行順序:

from,on,join,where,group by,having,select,distinct,union,order by,limit。

6. char(),binary()括號內的長度是指字符還是字節

char():5.0以上版本的使用字符存儲,5.0以下使用字節存儲。

binary():目前是以字節的形式存儲。

7. utf8與utf8mb4區別

MySQL在5.5.3之後增加了這個utf8mb4的編碼,mb4就是most bytes 4的意思,專門用來兼容四字節的unicode。好在utf8mb4是utf8的超集,除了將編碼改爲utf8mb4外不需要做其他轉換。utf8能夠存下大部分中文漢字,那爲什麼還要使用utf8mb4呢? 原來mysql支持的 utf8 編碼最大字符長度爲 3 字節,如果遇到 4 字節的寬字符就會插入異常了

8. char和binary區別 /* 未解決 */

(1)binary使用\0(零字節)填充,檢索時不會去掉填充物。

(2)binary使用字節碼按字節進行比較,區分大小寫。

  char按字符比較,不區分大小寫。

(3)使用binary進行比較速度比char快。

(4)mysql8中binary的使用與char大有不同,十分詭異。

9. 日期與時間戳轉換的函數

將時間戳轉日期的函數:FROM_UNIXTIME(unix_timestamp,format);

將日期轉時間戳的函數:UNIX_TIMESTAMP(date);

10. explain 執行計劃中個列的含義?

(1)select_type:

簡單

simple:查詢不包含子查詢和union,表示不包含複雜類型的查詢(join不屬於複雜類型查詢)

複雜

primary:查詢有任何複雜的子部分,則最外層部分標記爲primary,表示包含複雜類型查詢最外層

subquery:不在from子句中出現的子查詢(可以在select或where列表中出現)。

例如:
SELECT (SELECT actor_id FROM film_actor LIMIT 1) AS id,actor_id FROM actor;
SELECT actor_id FROM actor WHERE actor_id=(SELECT actor_id FROM film_actor LIMIT 1)

derived:在from子句中出現的子查詢

例如:
SELECT actor_id FROM(SELECT actor_id FROM film_actor LIMIT 1) AS tmp

union:union中的第二個和隨後的select被標記爲union

例如:
SELECT actor_id FROM actor UNION ALL SELECT actor.actor_id FROM film_actor INNER JOIN actor ON actor.`actor_id`=film_actor.`actor_id`;

(2)table

顯示順序根據左側深度優先樹生成,如下:

sql:

分析:

11. MySQL查詢過程

12. 如何減少count()時訪問行數

EXPLAIN
SELECT COUNT(1) FROM actor WHERE actor_id>5;


EXPLAIN
SELECT (SELECT COUNT(*) FROM actor)-COUNT(*) FROM actor WHERE actor_id<5;

13. 如何在查詢時不使用查詢緩存,MYSQL8已經取消查詢緩存

SELECT SQL_NO_CACHE * FROM customer WHERE first_name='CHRISTINA' AND last_name LIKE '%AN%';

14. 如何在一個查詢中統計同一個列的不同值的數量

SELECT SUM(color='red') AS recCnt,SUM(color='blue') AS blueCnt FROM table_name;

15. MySQL導入導出表數據方法

例如:

導出:SELECT * FROM actor INTO OUTFILE 'C:/ProgramData/MySQL/MySQL Server 8.0/Uploads/test2.sql';

若提示:The MySQL server is running with the --secure-file-priv option so it cannot execute this statement

可通過SHOW VARIABLES LIKE 'secure_file_priv'查看導出數據安全存放路徑

導入:LOAD DATA INFILE 'C:/ProgramData/MySQL/MySQL Server 8.0/Uploads/test2.sql' INTO TABLE actor;

16. MySQL計算字符串中字節長度函數,和字符串中字符多少函數

例如:

SELECT LENGTH('漢1');    -- 5 

SELECT LENGTH('?1');    -- 5

SELECT CHAR_LENGTH('漢1');    -- 2
SELECT CHAR_LENGTH('?1');    -- 2

17. MySQL8 查詢設置隔離級別

SHOW VARIABLES LIKE 'transaction_isolation';

SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

18. INNODB表導入效率優化

(1)導入數據按照主鍵順序排序

(2)SET unique_checks=0  -- 關閉唯一性校驗

(3)SET autocommit=0  -- 關閉自動提交

19. 可以使用show profile for query,查看是否使用查詢緩存,但僅限於mysql8以前,切記勿忘開查詢緩存。

20. MYISAM不會死鎖而InnoDB會死鎖的原因?

MyISAM 表 鎖 是 deadlock free 的, 這是 因爲 MyISAM 總是 一次 獲得 所需 的 全部 鎖, 要麼 全部 滿足, 要麼 等待, 因此 不會 出現 死鎖。 但在 InnoDB 中, 除 單個 SQL 組成 的 事務 外, 鎖 是 逐步 獲得 的, 這就 決定了 在 InnoDB 中 發生 死鎖 是 可能 的。

21. MYISAM鎖表時的併發操作

LOCK TABLES時加了‘local’選項,其作用就是在滿足MyISAM表併發插入條件的情況下,允許其他用戶在表尾插入記錄。

例如:LOCK tables orders read local,order_detail read local;

22.排查死鎖問題

SHOW ENGINE INNODB STATUS; -- 查看死鎖語句

23. mysqldumpslow.pl 使用

24.設置服務器和客戶端通信字符集

SET NAMES gbk; -- 或者SET CHARACTER SET utf8;

25.修改表的校對規則和字符集

ALTER TABLE tmp4 COLLATE utf8_bin;

ALTER TABLE tmp4 CHARACTER SET utf8;

26.修改字段的字符集和校對規則

ALTER TABLE tmp4 MODIFY COLUMN first_name VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_bin;

27.全文索引(fullIndex,基於5.7.6的ngram parser插件)

<1> 自然語言的全文索引:

如果想針對特定長度(ngram_token_size)進行切割(適合中文,不適合英文,英文按照空格切割),例如:松下電子,切割爲:松下 下電 電子

可以在my.ini中設置ngram_token_size=2,創建表時添加相應註釋即可

若不按照特定長度(不設置ngram_token_size)切割則默認根據空格切割,使用自然語言全文索引需注意ngram_token_size的大小。

<2> 布爾全文索引:

根據空格切割(不論中文、英文)。

<3> 注意:

(1)修改ngram_token_size,需要重啓服務並OPTIMIZE TABLE xx;

(2)不確定切割結果時可以使用如下查看。

  SET GLOBAL innodb_ft_aux_table="sakila/film_text2";

  SELECT * FROM information_schema.INNODB_FT_INDEX_TABLE;
  SELECT * FROM information_schema.INNODB_FT_INDEX_CACHE;

28.查看當前session的線程id:

SELECT @@pseudo_thread_id

29.RC隔離級別下不支持間隙鎖。

30.事務開啓時間是在第一個sql語句執行時,而不是begin執行時。

31. 在5.7版本中可以查看sys.innodb_lock_waits表來確定是哪個線程佔用鎖未釋放。

32. Innodb RR和RC隔離級別下,由於對非索引行查找需要進行全表掃描,所以對非索引行加鎖會導致全表鎖住。

33. Gap Lock是爲了解決幻讀問題,所以只有在RR隔離級別下才存在,由於對非索引查找需要進行全表掃描,所以對非索引字段加鎖會造成全表性的間隙鎖,如果對非主鍵索引查找,只會對其左右兩側的間隙上鎖,如果對主鍵索引查找,由於主鍵的自增特性所以不會加間隙鎖。

34. MySQL髒頁刷新問題

(1)可以通過下面語句查看髒頁比例:
SELECT VARIABLE_VALUE INTO @a FROM `performance_schema`.global_status WHERE VARIABLE_NAME = 'Innodb_buffer_pool_pages_dirty';
SELECT VARIABLE_VALUE INTO @b FROM `performance_schema`.global_status WHERE VARIABLE_NAME = 'Innodb_buffer_pool_pages_total';
SELECT @a/@b;

(2)如果髒頁比例接近75%,就要檢查innodb_io_capacity設置的是否合理,innodb_io_capacity建議設置爲磁盤的IOPS。

(3)IOPS獲取方式,可以通過fio工具,命令如下:

fio -filename=/tmp/test_randrw -direct=1 -iodepth 1 -thread -rw=randrw -ioengine=psync -bs=16k -size=2G -numjobs=10 -runtime=60 -group_reporting -name=mytest

35. 如何使用optimizer_trace去分析order by語句。
/* 打開optimizer_trace,只對本線程有效 */
SET optimizer_trace='enabled=on'; 

/* @a保存Innodb_rows_read的初始值 */
select VARIABLE_VALUE into @a from  performance_schema.session_status where variable_name = 'Innodb_rows_read';

/* 執行語句 */
select city, name,age from t where city='杭州' order by name limit 1000; 

/* 查看 OPTIMIZER_TRACE 輸出 */
SELECT * FROM `information_schema`.`OPTIMIZER_TRACE`\G

/* @b保存Innodb_rows_read的當前值 */
select VARIABLE_VALUE into @b from performance_schema.session_status where variable_name = 'Innodb_rows_read';

/* 計算Innodb_rows_read差值 */
select @b-@a;

optimizer_trace結果圖:

36. 如何查看mysql binlog?

可以使用mysqlbing工具查看mysql binlog

mysqlbinlog工具存放在mysql bin目錄下,例如:C:\Program Files\MySQL\MySQL Server 8.0\bin

mysql binlog日誌存放在Data目錄下,例如:C:\ProgramData\MySQL\MySQL Server 8.0\Data

使用mysqlbing分析時可以將需分析的binlog放到D盤根目錄,然後使用如下命令分析:

C:\Program Files\MySQL\MySQL Server 8.0\bin>mysqlbinlog -vv D:\binlog.000104 --start-position=8092

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章