簡體   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