我在mysql5.6中有一个表cdc_bond_valuation:
+--------------+--------------------+--------------+---------------------------------+--------------+--------------+-------------+
| table_schema | table_name | index_schema | index_name | seq_in_index | column_name | cardinality |
+--------------+--------------------+--------------+---------------------------------+--------------+--------------+-------------+
| ss_product | cdc_bond_valuation | ss_product | IDX_cdc_bond_valuation_Bond_Key | 1 | Bond_Key | 377844 |
| ss_product | cdc_bond_valuation | ss_product | IndexValuateDate | 1 | Valuate_Date | 143025 |
| ss_product | cdc_bond_valuation | ss_product | PRIMARY | 1 | ID | 25315548 |
+--------------+--------------------+--------------+---------------------------------+--------------+--------------+-------------+
query 1:
SELECT Valuate_Date FROM cdc_bond_valuation WHERE Valuate_Date = 20181203;
query 2:
SELECT ID, Valuate_Date FROM cdc_bond_valuation WHERE Valuate_Date = 20181203;
query 3:
SELECT Bond_Key FROM cdc_bond_valuation WHERE Valuate_Date = 20181203;
query 4:
SELECT Bond_Key,Valuate_Date FROM cdc_bond_valuation WHERE Valuate_Date = 20181203;
explain 1:
mysql> explain SELECT Valuate_Date FROM cdc_bond_valuation WHERE Valuate_Date = 20181203;
+----+-------------+--------------------+------+------------------+------------------+---------+-------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------------+------+------------------+------------------+---------+-------+-------+-------------+
| 1 | SIMPLE | cdc_bond_valuation | ref | IndexValuateDate | IndexValuateDate | 5 | const | 98156 | Using index |
+----+-------------+--------------------+------+------------------+------------------+---------+-------+-------+-------------+
1 row in set
explain 2:
mysql> explain SELECT ID,Valuate_Date FROM cdc_bond_valuation WHERE Valuate_Date = 20181203;
+----+-------------+--------------------+------+------------------+------------------+---------+-------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------------+------+------------------+------------------+---------+-------+-------+-------------+
| 1 | SIMPLE | cdc_bond_valuation | ref | IndexValuateDate | IndexValuateDate | 5 | const | 98156 | Using index |
+----+-------------+--------------------+------+------------------+------------------+---------+-------+-------+-------------+
1 row in set
explain 3:
mysql> explain SELECT Bond_Key FROM cdc_bond_valuation WHERE Valuate_Date = 20181203;
+----+-------------+--------------------+------+------------------+------------------+---------+-------+-------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------------+------+------------------+------------------+---------+-------+-------+-------+
| 1 | SIMPLE | cdc_bond_valuation | ref | IndexValuateDate | IndexValuateDate | 5 | const | 98156 | NULL |
+----+-------------+--------------------+------+------------------+------------------+---------+-------+-------+-------+
1 row in set
explain 4:
mysql> explain SELECT Bond_Key,Valuate_Date FROM cdc_bond_valuation WHERE Valuate_Date = 20181203;
+----+-------------+--------------------+------+------------------+------------------+---------+-------+-------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------------+------+------------------+------------------+---------+-------+-------+-------+
| 1 | SIMPLE | cdc_bond_valuation | ref | IndexValuateDate | IndexValuateDate | 5 | const | 98156 | NULL |
+----+-------------+--------------------+------+------------------+------------------+---------+-------+-------+-------+
1 row in set
mysql> select table_schema,
table_name,
index_schema,
index_name,
seq_in_index,
column_name,
cardinality
from information_schema.statistics
where table_name = 'cdc_bond_valuation'
order by table_schema, table_name, index_name, seq_in_index;
+--------------+--------------------+--------------+---------------------------------+--------------+--------------+-------------+
| table_schema | table_name | index_schema | index_name | seq_in_index | column_name | cardinality |
+--------------+--------------------+--------------+---------------------------------+--------------+--------------+-------------+
| ss_product | cdc_bond_valuation | ss_product | IDX_cdc_bond_valuation_Bond_Key | 1 | Bond_Key | 377844 |
| ss_product | cdc_bond_valuation | ss_product | IndexValuateDate | 1 | Valuate_Date | 143025 |
| ss_product | cdc_bond_valuation | ss_product | PRIMARY | 1 | ID | 25315548 |
+--------------+--------------------+--------------+---------------------------------+--------------+--------------+-------------+
3 rows in set
mysql>
如上表中有4个查询,它们都使用索引IndexValuateDate,但是查询1和2很快(不到1秒),但是查询3和4却很慢(超过1000秒)。
我注意到1和2仅使用索引来反馈查询(ID是主键,而Valuate_Date已索引)。 3和4首先使用Valuate_Date上的索引过滤表,然后返回表以获取具有rowid的列?为什么不只使用像1和2这样的索引,因为Bond_Key也被索引了?
答案 0 :(得分:0)
请提供SHOW CREATE TABLE
。
InnoDB静默地将PRIMARY KEY
的列添加到每个辅助键。因此,查询1和2执行相同。他们只使用索引。这在EXPLAIN
中用Using index
表示。也就是说,INDEX(Valuate_Date)
包含所需的列,而其他列则不需要。
EXPLAINs
指示使用了相同的索引,但未“覆盖”(未提及Using index
)。因此,对索引进行了线性扫描,但是对于该日期的估计98156个条目中的每个条目,它必须(在数据的BTree中)查找Bond_Key
的值。这种额外的查找导致严重的速度下降。 (1000秒与在HDD上执行98156磁盘命中匹配得很好。)
要快速进行所有4个查询,请用此复合索引替换IndexValuateDate
,并按给定的顺序排列列:
INDEX(Valuate_Date, Bond_Key, ID)
我可以建议您通过DATE
数据类型而不是DECIMAL(8,0)
处理日期。
与其他数据库不同,MySQL没有“ rowid”。而是在树中使用PRIMARY KEY
来对数据进行排序。
答案 1 :(得分:0)
CREATE TABLE `cdc_bond_valuation` (
`ID` varchar(32) NOT NULL,
`Bond_Key` varchar(25) DEFAULT NULL,
`Short_Name` varchar(32) DEFAULT NULL,
`Bond_ID` varchar(32) DEFAULT NULL,
`Valuate_Date` decimal(8,0) DEFAULT NULL,
`Listed_Market` varchar(3) DEFAULT NULL,
`Remaining_Year` decimal(7,4) DEFAULT NULL,
`Val_Intraday_Dirty_Price` decimal(7,4) DEFAULT NULL,
`Val_Intraday_Accrued_Interest` decimal(7,4) DEFAULT NULL,
`Val_Clean_Price` decimal(7,4) DEFAULT NULL,
`Val_Yield` decimal(7,4) DEFAULT NULL,
`Val_Modified_Duration` decimal(7,4) DEFAULT NULL,
`Val_Convexity` decimal(7,4) DEFAULT NULL,
`Val_Basis_Point_Value` decimal(7,4) DEFAULT NULL,
`Val_Spread_Duration` decimal(7,4) DEFAULT NULL,
`Val_Spread_Convexity` decimal(7,4) DEFAULT NULL,
`Market_Dirty_Price` decimal(7,4) DEFAULT NULL,
`Market_Clean_Price` decimal(7,4) DEFAULT NULL,
`Market_Yield` decimal(7,4) DEFAULT NULL,
`Market_Modified_Duration` decimal(7,4) DEFAULT NULL,
`Market_Convexity` decimal(7,4) DEFAULT NULL,
`Market_Basis_Point_Value` decimal(7,4) DEFAULT NULL,
`Market_Spread_Duration` decimal(7,4) DEFAULT NULL,
`Market_Spread_Convexity` decimal(7,4) DEFAULT NULL,
`Credibility` varchar(16) DEFAULT NULL,
`Val_Rate_Duration` decimal(7,4) DEFAULT NULL,
`Val_Rate_Convexity` decimal(7,4) DEFAULT NULL,
`Market_Rate_Duration` decimal(7,4) DEFAULT NULL,
`Market_Rate_Convexity` decimal(7,4) DEFAULT NULL,
`Val_Closed_Dirty_Price` decimal(7,4) DEFAULT NULL,
`Val_Closed_Accrued_Interest` decimal(7,4) DEFAULT NULL,
`Remaining_Par_Value` decimal(7,4) DEFAULT NULL,
`Val_Spread` decimal(7,4) DEFAULT NULL,
`Yield_Curve_ID` varchar(128) DEFAULT NULL,
`Market_Spread` decimal(7,4) DEFAULT NULL,
`Absolute_Liquidity_Coefficient` decimal(7,4) DEFAULT NULL,
`Position_Percentage` decimal(7,4) DEFAULT NULL,
`Relative_Liquidity_Coefficient` decimal(7,4) DEFAULT NULL,
`Relative_Liquidity_Value` decimal(7,4) DEFAULT NULL,
`Option` varchar(8) DEFAULT NULL ,
PRIMARY KEY (`ID`),
KEY `IndexValuateDate` (`Valuate_Date`) USING BTREE,
KEY `ValuateDateBondKey` (`Valuate_Date`,`Bond_Key`),
KEY `IndexBondKey` (`Bond_Key`,`Listed_Market`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8
答案 2 :(得分:0)
查询5:
mysql> explain SELECT Bond_Key, Valuate_Date FROM cdc_bond_valuation WHERE Valuate_Date = 20181203 and bond_key='C0000832017CORLEB01';
+----+-------------+--------------------+------+--------------------------------------------------+---------------------------------+---------+-------+------+------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------------+------+--------------------------------------------------+---------------------------------+---------+-------+------+------------------------------------+
| 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 |
+----+-------------+--------------------+------+--------------------------------------------------+---------------------------------+---------+-------+------+------------------------------------+
1 row in set
mysql>
查询5使用index(bond_key)进行过滤,然后像全表scann一样扫描结果(787行)以查找bond_key。查询5根本不使用index(ValuateDate)。是吗?
答案 3 :(得分:0)
SELECT count(*) FROM cdc_bond_valuation WHERE bond_key='C0000832017CORLEB01';
SELECT count(*) FROM cdc_bond_valuation WHERE bond_key='C0000832017CORLEB01' and Valuate_Date = 20181203;
+----------+
| count(*) |
+----------+
| 788 |
+----------+
1 row in set
+----------+
| count(*) |
+----------+
| 2 |
+----------+
1 row in set
mysql>