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

时间:2017-03-25 10:46:33

标签: mysql database indexing query-performance

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

这是表格结构。

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 |
+------+-------------+----------------+------+---------------+------+---------+------+-------+-------------+
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:2)

答案在解释计划的行列中

在第一种情况下,您有352

在第二个15779

这表明在两个查询之间查询优化器的不同策略。

也可能是您正在不同的服务器中执行这两个查询,或者在解释

的情况下执行其他不同的条件

答案 1 :(得分:0)

(sqlbot&#39;评论回答了这个问题。)

此复合索引可以进一步优化

INDEX(actual_sale, startdate)

但是,这可能会很有效actual_sale NULL&#39;太频繁&#39;。否则,全表扫描会更好,但优化器可能无法解决这个问题。

您的许多列都被认为过大。这种过度行为可能会导致性能问题。