为什么在MySQL5.6中选择不同的列会影响查询速度?

rjjhvcjd  于 2021-06-18  发布在  Mysql
关注(0)|答案(4)|浏览(513)

我在mysql5.6中有一个表cdc\u bond\u valuation:

  1. +--------------+--------------------+--------------+---------------------------------+--------------+--------------+-------------+
  2. | table_schema | table_name | index_schema | index_name | seq_in_index | column_name | cardinality |
  3. +--------------+--------------------+--------------+---------------------------------+--------------+--------------+-------------+
  4. | ss_product | cdc_bond_valuation | ss_product | IDX_cdc_bond_valuation_Bond_Key | 1 | Bond_Key | 377844 |
  5. | ss_product | cdc_bond_valuation | ss_product | IndexValuateDate | 1 | Valuate_Date | 143025 |
  6. | ss_product | cdc_bond_valuation | ss_product | PRIMARY | 1 | ID | 25315548 |
  7. +--------------+--------------------+--------------+---------------------------------+--------------+--------------+-------------+
  8. query 1:
  9. SELECT Valuate_Date FROM cdc_bond_valuation WHERE Valuate_Date = 20181203;
  10. query 2:
  11. SELECT ID, Valuate_Date FROM cdc_bond_valuation WHERE Valuate_Date = 20181203;
  12. query 3:
  13. SELECT Bond_Key FROM cdc_bond_valuation WHERE Valuate_Date = 20181203;
  14. query 4:
  15. SELECT Bond_Key,Valuate_Date FROM cdc_bond_valuation WHERE Valuate_Date = 20181203;
  16. explain 1:
  17. mysql> explain SELECT Valuate_Date FROM cdc_bond_valuation WHERE Valuate_Date = 20181203;
  18. +----+-------------+--------------------+------+------------------+------------------+---------+-------+-------+-------------+
  19. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  20. +----+-------------+--------------------+------+------------------+------------------+---------+-------+-------+-------------+
  21. | 1 | SIMPLE | cdc_bond_valuation | ref | IndexValuateDate | IndexValuateDate | 5 | const | 98156 | Using index |
  22. +----+-------------+--------------------+------+------------------+------------------+---------+-------+-------+-------------+
  23. 1 row in set
  24. explain 2:
  25. mysql> explain SELECT ID,Valuate_Date FROM cdc_bond_valuation WHERE Valuate_Date = 20181203;
  26. +----+-------------+--------------------+------+------------------+------------------+---------+-------+-------+-------------+
  27. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  28. +----+-------------+--------------------+------+------------------+------------------+---------+-------+-------+-------------+
  29. | 1 | SIMPLE | cdc_bond_valuation | ref | IndexValuateDate | IndexValuateDate | 5 | const | 98156 | Using index |
  30. +----+-------------+--------------------+------+------------------+------------------+---------+-------+-------+-------------+
  31. 1 row in set
  32. explain 3:
  33. mysql> explain SELECT Bond_Key FROM cdc_bond_valuation WHERE Valuate_Date = 20181203;
  34. +----+-------------+--------------------+------+------------------+------------------+---------+-------+-------+-------+
  35. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  36. +----+-------------+--------------------+------+------------------+------------------+---------+-------+-------+-------+
  37. | 1 | SIMPLE | cdc_bond_valuation | ref | IndexValuateDate | IndexValuateDate | 5 | const | 98156 | NULL |
  38. +----+-------------+--------------------+------+------------------+------------------+---------+-------+-------+-------+
  39. 1 row in set
  40. explain 4:
  41. mysql> explain SELECT Bond_Key,Valuate_Date FROM cdc_bond_valuation WHERE Valuate_Date = 20181203;
  42. +----+-------------+--------------------+------+------------------+------------------+---------+-------+-------+-------+
  43. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  44. +----+-------------+--------------------+------+------------------+------------------+---------+-------+-------+-------+
  45. | 1 | SIMPLE | cdc_bond_valuation | ref | IndexValuateDate | IndexValuateDate | 5 | const | 98156 | NULL |
  46. +----+-------------+--------------------+------+------------------+------------------+---------+-------+-------+-------+
  47. 1 row in set
  48. mysql> select table_schema,
  49. table_name,
  50. index_schema,
  51. index_name,
  52. seq_in_index,
  53. column_name,
  54. cardinality
  55. from information_schema.statistics
  56. where table_name = 'cdc_bond_valuation'
  57. order by table_schema, table_name, index_name, seq_in_index;
  58. +--------------+--------------------+--------------+---------------------------------+--------------+--------------+-------------+
  59. | table_schema | table_name | index_schema | index_name | seq_in_index | column_name | cardinality |
  60. +--------------+--------------------+--------------+---------------------------------+--------------+--------------+-------------+
  61. | ss_product | cdc_bond_valuation | ss_product | IDX_cdc_bond_valuation_Bond_Key | 1 | Bond_Key | 377844 |
  62. | ss_product | cdc_bond_valuation | ss_product | IndexValuateDate | 1 | Valuate_Date | 143025 |
  63. | ss_product | cdc_bond_valuation | ss_product | PRIMARY | 1 | ID | 25315548 |
  64. +--------------+--------------------+--------------+---------------------------------+--------------+--------------+-------------+
  65. 3 rows in set
  66. mysql>

表上有4个查询,它们都使用索引indexevaluedate,但是查询1和查询2非常快(不到1秒),但是查询3和查询4非常慢(超过1000秒)。
我注意到1和2只是使用索引来反馈查询(id是主键,evalue\u date是索引)。3和4首先使用evalue\ u date上的索引来筛选表,然后返回到表get column with rowid?为什么不直接使用像1和2这样的索引,因为键也被索引了?

ujv3wf0j

ujv3wf0j1#

  1. SELECT count(*) FROM cdc_bond_valuation WHERE bond_key='C0000832017CORLEB01';
  2. SELECT count(*) FROM cdc_bond_valuation WHERE bond_key='C0000832017CORLEB01' and Valuate_Date = 20181203;
  3. +----------+
  4. | count(*) |
  5. +----------+
  6. | 788 |
  7. +----------+
  8. 1 row in set
  9. +----------+
  10. | count(*) |
  11. +----------+
  12. | 2 |
  13. +----------+
  14. 1 row in set
  15. mysql>
vbkedwbf

vbkedwbf2#

  1. CREATE TABLE `cdc_bond_valuation` (
  2. `ID` varchar(32) NOT NULL,
  3. `Bond_Key` varchar(25) DEFAULT NULL,
  4. `Short_Name` varchar(32) DEFAULT NULL,
  5. `Bond_ID` varchar(32) DEFAULT NULL,
  6. `Valuate_Date` decimal(8,0) DEFAULT NULL,
  7. `Listed_Market` varchar(3) DEFAULT NULL,
  8. `Remaining_Year` decimal(7,4) DEFAULT NULL,
  9. `Val_Intraday_Dirty_Price` decimal(7,4) DEFAULT NULL,
  10. `Val_Intraday_Accrued_Interest` decimal(7,4) DEFAULT NULL,
  11. `Val_Clean_Price` decimal(7,4) DEFAULT NULL,
  12. `Val_Yield` decimal(7,4) DEFAULT NULL,
  13. `Val_Modified_Duration` decimal(7,4) DEFAULT NULL,
  14. `Val_Convexity` decimal(7,4) DEFAULT NULL,
  15. `Val_Basis_Point_Value` decimal(7,4) DEFAULT NULL,
  16. `Val_Spread_Duration` decimal(7,4) DEFAULT NULL,
  17. `Val_Spread_Convexity` decimal(7,4) DEFAULT NULL,
  18. `Market_Dirty_Price` decimal(7,4) DEFAULT NULL,
  19. `Market_Clean_Price` decimal(7,4) DEFAULT NULL,
  20. `Market_Yield` decimal(7,4) DEFAULT NULL,
  21. `Market_Modified_Duration` decimal(7,4) DEFAULT NULL,
  22. `Market_Convexity` decimal(7,4) DEFAULT NULL,
  23. `Market_Basis_Point_Value` decimal(7,4) DEFAULT NULL,
  24. `Market_Spread_Duration` decimal(7,4) DEFAULT NULL,
  25. `Market_Spread_Convexity` decimal(7,4) DEFAULT NULL,
  26. `Credibility` varchar(16) DEFAULT NULL,
  27. `Val_Rate_Duration` decimal(7,4) DEFAULT NULL,
  28. `Val_Rate_Convexity` decimal(7,4) DEFAULT NULL,
  29. `Market_Rate_Duration` decimal(7,4) DEFAULT NULL,
  30. `Market_Rate_Convexity` decimal(7,4) DEFAULT NULL,
  31. `Val_Closed_Dirty_Price` decimal(7,4) DEFAULT NULL,
  32. `Val_Closed_Accrued_Interest` decimal(7,4) DEFAULT NULL,
  33. `Remaining_Par_Value` decimal(7,4) DEFAULT NULL,
  34. `Val_Spread` decimal(7,4) DEFAULT NULL,
  35. `Yield_Curve_ID` varchar(128) DEFAULT NULL,
  36. `Market_Spread` decimal(7,4) DEFAULT NULL,
  37. `Absolute_Liquidity_Coefficient` decimal(7,4) DEFAULT NULL,
  38. `Position_Percentage` decimal(7,4) DEFAULT NULL,
  39. `Relative_Liquidity_Coefficient` decimal(7,4) DEFAULT NULL,
  40. `Relative_Liquidity_Value` decimal(7,4) DEFAULT NULL,
  41. `Option` varchar(8) DEFAULT NULL ,
  42. PRIMARY KEY (`ID`),
  43. KEY `IndexValuateDate` (`Valuate_Date`) USING BTREE,
  44. KEY `ValuateDateBondKey` (`Valuate_Date`,`Bond_Key`),
  45. KEY `IndexBondKey` (`Bond_Key`,`Listed_Market`) USING BTREE
  46. ) ENGINE=InnoDB DEFAULT CHARSET=utf8
展开查看全部
bq3bfh9z

bq3bfh9z3#

问题5:

  1. mysql> explain SELECT Bond_Key, Valuate_Date FROM cdc_bond_valuation WHERE Valuate_Date = 20181203 and bond_key='C0000832017CORLEB01';
  2. +----+-------------+--------------------+------+--------------------------------------------------+---------------------------------+---------+-------+------+------------------------------------+
  3. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  4. +----+-------------+--------------------+------+--------------------------------------------------+---------------------------------+---------+-------+------+------------------------------------+
  5. | 1 | SIMPLE | cdc_bond_valuation | ref | IndexValuateDate,IDX_cdc_bond_valuation_Bond_Key | IDX_cdc_bond_valuation_Bond_Key | 78 | const | 787 | Using index condition; Using where |
  6. +----+-------------+--------------------+------+--------------------------------------------------+---------------------------------+---------+-------+------+------------------------------------+
  7. 1 row in set
  8. mysql>

查询5使用索引(bond\u key)进行过滤,然后像对bond\u key的full table scann一样扫描结果(787行)。查询5根本不使用索引(valuedate)。是这样吗?

omvjsjqw

omvjsjqw4#

请提供 SHOW CREATE TABLE .
innodb默默地添加 PRIMARY KEY 到每个辅助键。因此,查询1和查询2的执行方式相同。他们只使用索引。如中所示 EXPLAINUsing index . 也就是说, INDEX(Valuate_Date) 包含所需的列,其他列不需要。
这个 EXPLAINs 表明使用了相同的索引,但不是“覆盖”(未提及 Using index ). 所以索引是线性扫描的,但是对于那个日期估计的98156个条目中的每一个,它必须(在数据的btree中)查找 Bond_Key . 这个额外的查找导致了严重的减速(1000秒与硬盘上的98156次磁盘点击非常匹配。)
要快速完成所有4个查询,请替换 IndexValuateDate 使用此复合索引,并按给定顺序放置列:

  1. INDEX(Valuate_Date, Bond_Key, ID)

我可以建议你通过 DATE 数据类型,不是 DECIMAL(8,0) .
与其他数据库不同,mysql没有“rowid”。取而代之的是 PRIMARY KEY 在btree中用于对数据进行排序。

相关问题