繁体   English   中英

MySQL有时不使用INDEX,但有时会使用

[英]MySQL sometimes not using the INDEX but sometimes it does

有时我的查询未使用索引,但有时会使用索引。 你们能解释一下为什么会这样吗?

这是表结构。

MariaDB [crm]> desc vtiger_project;
+------------------------+---------------+------+-----+---------+-------+
| Field                  | Type          | Null | Key | Default | Extra |
+------------------------+---------------+------+-----+---------+-------+
| projectid              | int(11)       | NO   | PRI | 0       |       |
| projectname            | varchar(100)  | YES  |     | NULL    |       |
| projecttype            | varchar(50)   | YES  |     | NULL    |       |
| siteaddress            | varchar(500)  | YES  |     | NULL    |       |
| state                  | varchar(100)  | YES  |     | NULL    |       |
| district               | varchar(100)  | YES  |     | NULL    |       |
| city                   | varchar(100)  | YES  |     | NULL    |       |
| pincode                | varchar(100)  | YES  |     | NULL    |       |
| phone                  | varchar(100)  | YES  |     | NULL    |       |
| startdate              | date          | YES  | MUL | NULL    |       |
| branch                 | varchar(100)  | YES  |     | NULL    |       |
| customer               | int(11)       | YES  | MUL | NULL    |       |
| dealer                 | int(11)       | YES  |     | NULL    |       |
| contractor             | int(11)       | YES  | MUL | NULL    |       |
| architect              | int(11)       | YES  | MUL | NULL    |       |
| carpenter              | int(11)       | YES  | MUL | NULL    |       |
| productcategory        | varchar(100)  | YES  |     | NULL    |       |
| brand_preferred        | varchar(100)  | YES  |     | NULL    |       |
| formal_spec_check      | varchar(3)    | YES  |     | NULL    |       |
| formal_spec_details    | varchar(250)  | YES  |     | NULL    |       |
| projectstatus          | varchar(25)   | YES  |     | NULL    |       |
| project_reason_loosing | varchar(100)  | YES  |     | NULL    |       |
| reason_loosing_deatils | varchar(250)  | YES  |     | NULL    |       |
| reason_winning_deatils | varchar(250)  | YES  |     | NULL    |       |
| adjustment             | decimal(25,8) | YES  |     | NULL    |       |
| exciseduty             | decimal(25,3) | YES  |     | NULL    |       |
| total                  | decimal(25,8) | YES  |     | NULL    |       |
| subtotal               | decimal(25,8) | YES  |     | NULL    |       |
| taxtype                | varchar(25)   | YES  |     | NULL    |       |
| discount_percent       | decimal(25,3) | YES  |     | NULL    |       |
| discount_amount        | decimal(25,8) | YES  |     | NULL    |       |
| s_h_amount             | decimal(25,8) | YES  |     | NULL    |       |
| currency_id            | int(19)       | NO   |     | 1       |       |
| conversion_rate        | decimal(10,3) | NO   |     | 1.000   |       |
| actual_sale            | varchar(255)  | YES  |     | NULL    |       |
| expected_sale_in_na    | varchar(255)  | YES  |     | NULL    |       |
| primary_decision_maker | varchar(100)  | YES  |     | NULL    |       |
+------------------------+---------------+------+-----+---------+-------+

正如您在下面的输出中看到的那样,第一个查询确实命中了索引,但第二个查询没有命中索引,我对该查询所做的唯一更改是startdate部分。 我究竟做错了什么?

 MariaDB [crm]> explain SELECT -> COUNT(projectid) -> FROM -> vtiger_project -> WHERE -> 82582 IN (customer , contractor, architect, carpenter) -> AND projectstatus NOT IN ('Supplied' , 'Closed As Complete', 'Closed As Lost') -> AND actual_sale IS NULL -> AND startdate > NOW() -> ; +------+-------------+----------------+-------+---------------+---------------+---------+------+------+------------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +------+-------------+----------------+-------+---------------+---------------+---------+------+------+------------------------------------+ | 1 | SIMPLE | vtiger_project | range | startdate_idx | startdate_idx | 4 | NULL | 352 | Using index condition; Using where | +------+-------------+----------------+-------+---------------+---------------+---------+------+------+------------------------------------+ 1 row in set (0.00 sec) MariaDB [crm]> explain SELECT -> COUNT(projectid) -> FROM -> vtiger_project -> WHERE -> 82582 IN (customer , contractor, architect, carpenter) -> AND projectstatus NOT IN ('Supplied' , 'Closed As Complete', 'Closed As Lost') -> AND actual_sale IS NULL -> AND startdate < NOW() -> ; +------+-------------+----------------+------+---------------+------+---------+------+-------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +------+-------------+----------------+------+---------------+------+---------+------+-------+-------------+ | 1 | SIMPLE | vtiger_project | ALL | startdate_idx | NULL | NULL | NULL | 15779 | Using where | +------+-------------+----------------+------+---------------+------+---------+------+-------+-------------+ 

答案在解释计划的行列中

在第一种情况下,您有352

在第二个15779

这建议查询优化器两个查询之间的不同策略。

也可能是您在不同的服务器中执行两个查询,或者在其他不同条件下无法执行explain。

(sqlbot的评论回答了该问题。)

此复合索引可能会提供进一步的优化:

INDEX(actual_sale, startdate)

但是,这可能会很好地工作,只有actual_sale不是“太频繁”为NULL 否则,全表扫描会更好,但是优化器可能无法解决这一问题。

您看到的许多列过大。 这样的过度可能导致性能问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM