【发布时间】:2019-10-07 13:39:24
【问题描述】:
我正在尝试执行 SQL 查询。不幸的是,它不使用索引,而是进行表扫描。
我已经创建了以下索引:
- PRIMARY($phone, $$fc_date)
- idx $$fc_status_detail
- idx $$fc_date
- idx $$fc_status
- idx $$电话
另外,我复制了表格,但这也没有提供任何有用的结果。
这是表结构:
+--------------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------------+--------------+------+-----+---------+-------+
| $id | varchar(100) | NO | | NULL | |
| $created_date | varchar(100) | YES | | NULL | |
| $phone | varchar(100) | NO | PRI | NULL | |
| $source | varchar(100) | YES | | NULL | |
| Orga | varchar(100) | YES | | NULL | |
| Anrede | varchar(100) | YES | | NULL | |
| Vorname | varchar(100) | YES | | NULL | |
| Zuname | varchar(100) | YES | | NULL | |
| Strasse | varchar(100) | YES | | NULL | |
| PLZ | varchar(100) | YES | | NULL | |
| Ort | varchar(100) | YES | | NULL | |
| Geburtsdatum | varchar(100) | YES | | NULL | |
| Email | varchar(100) | YES | | NULL | |
| Zeitschrift | varchar(100) | YES | | NULL | |
| Herkunft | varchar(100) | YES | | NULL | |
| Zeitschrift_Titel | varchar(100) | YES | | NULL | |
| telefon | varchar(100) | YES | | NULL | |
| Stornogrund | varchar(100) | YES | | NULL | |
| Storno | varchar(100) | YES | | NULL | |
| Telefonnummer | varchar(100) | YES | | NULL | |
| Postleitzahl | varchar(100) | YES | | NULL | |
| Geburtsjahr | varchar(100) | YES | | NULL | |
| $$fc_task | varchar(100) | YES | | NULL | |
| $$fc_user | varchar(100) | YES | | NULL | |
| $$fc_date | varchar(100) | NO | PRI | NULL | |
| $$fc_status | varchar(100) | YES | MUL | NULL | |
| $$fc_status_detail | varchar(100) | YES | MUL | NULL | |
| $$qc_task | varchar(100) | YES | | NULL | |
| $$qc_user | varchar(100) | YES | | NULL | |
| $$qc_date | varchar(100) | YES | | NULL | |
| $$qc_status | varchar(100) | YES | | NULL | |
| $$qc_status_detail | varchar(100) | YES | | NULL | |
| $call_duration | smallint(6) | YES | | NULL | |
| $call_attempts | smallint(6) | YES | | NULL | |
+--------------------+--------------+------+-----+---------+-------+
这是查询:
EXPLAIN SELECT
count(*) as total,
CONCAT(case when c1.$$fc_date < 240 then "short" else "long" end, "/", c1.$$fc_status, "/", c1.$$fc_status_detail) as ergebnis,
sum(case when c2.$$fc_status = 'success' then 1 else 0 end)/ count(*) as c2_succes_rate
FROM
contacts c1 FORCE INDEX (PRIMARY),
contacts_copy c2
WHERE
c1.$phone = c2.$phone
and c1.$$fc_date < c2.$$fc_date
group by
ergebnis
这是结果:
+------+-------------+-------+------+--------------------------------------------------------------+---------+---------+---------------+---------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+------+--------------------------------------------------------------+---------+---------+---------------+---------+---------------------------------+
| 1 | SIMPLE | c1 | ALL | PRIMARY | NULL | NULL | NULL | 2017450 | Using temporary; Using filesort |
| 1 | SIMPLE | c2 | ref | PRIMARY,contacts_copy_$phone_IDX,contacts_copy_$$fc_date_IDX | PRIMARY | 402 | nmv.c1.$phone | 1 | Using where |
+------+-------------+-------+------+--------------------------------------------------------------+---------+---------+---------------+---------+---------------------------------+
正如您在第 1 行中看到的,虽然它识别主键,但它不使用它。问题是它扫描了 2 Mio。行,查询持续至少 5 分钟。
谁能解释一下,可能是什么问题?
【问题讨论】:
-
你能提供表格定义吗?我的印象是您正在尝试动态创建索引,而这正是占用您时间的原因。此外,如果没有这些,很难“调试”查询
-
我已将结构包含在我的帖子中。
-
由于我们不需要事务,我已经从 InnoDB 切换到 MyISAM Engine,但这并没有帮助。我已将“innodb_buffer_pool_size”增加到“5G”,但这也无济于事。
-
你试过用
JOIN contacts_copy c2 ON c1.$phone = c2.$phone and c1.$$fc_date < c2.$$fc_date代替where吗? -
@MarkoSeidenglanz 见Why should I provide an MCVE for what seems to me to be a very simple SQL query? 你能提供示例数据和预期结果吗.. 也许你的查询有更好的重写,结果相同但性能更好.. 另外我们必须知道你的 MySQL 版本因为在 MySQL 8.0 中获取连续记录更容易。我们也可以更好地测试优化,因为我们有数据优化器计划可以根据数据大小而改变。..
标签: mysql indexing mariadb explain