【发布时间】:2020-11-23 17:29:51
【问题描述】:
我第一次在使用 EXISTS 时遇到了一个我没有想到的问题。我有一张包含患者 ID 和咨询日期的表格,并尝试选择具有相同咨询日期的多条记录的患者:
-- total rows in vital: 732,527
-- number of rows after selection: 7,817
-- number of rows with multiple pat_id/kons_dt: 809
SELECT a.*
FROM emr.vital a
WHERE EXISTS (SELECT 1
FROM (SELECT pat_id, kons_dt, COUNT(*)
FROM emr.vital b
GROUP BY pat_id, kons_dt
HAVING COUNT(*) > 1
) b
WHERE a.pat_id = b.pat_id
)
这给了我以下结果(只有前 4 行):
+--------+---------------+
| pat_id | kons_dt |
+--------+---------------+
| 21384 | 2018-06-29 |
| 21384 | 2018-06-29 |
| 21888 | 2017-04-04 |
| 21888 | 2017-04-04 |
| ... | ... |
+--------+---------------+
表emr.vital没有索引。如果我添加一个索引:
CREATE INDEX id ON emr.vital(pat_id);
并运行相同的代码没有选择记录。我尝试创建一个最小示例,但没有成功获得相同的结果,也就是说,无论有无索引,我都得到了相同的结果。
也许 EXPLAIN 摘录可以提供一些想法:
无索引:
+----+--------------+-------------+--------+---------------+--------------+---------+-----------+--------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------+-------------+--------+---------------+--------------+---------+-----------+--------+---------------------------------+
| 1 | PRIMARY | a | ALL | \N | \N | \N | \N | 734988 | Using filesort |
| 1 | PRIMARY | <subquery2> | eq_ref | distinct_key | distinct_key | 7 | func,func | 1 | |
| 2 | MATERIALIZED | <derived3> | ALL | \N | \N | \N | \N | 734988 | |
| 3 | DERIVED | b | ALL | \N | \N | \N | \N | 734988 | Using temporary; Using filesort |
+----+--------------+-------------+--------+---------------+--------------+---------+-----------+--------+---------------------------------+
和带索引:
+----+-----------------+-------------+--------+---------------+--------------+---------+----------------------------+--------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-----------------+-------------+--------+---------------+--------------+---------+----------------------------+--------+----------------------------------------------+
| 1 | PRIMARY | a | ALL | pat_id | \N | \N | \N | 734988 | Using filesort |
| 1 | PRIMARY | <subquery2> | eq_ref | distinct_key | distinct_key | 4 | func | 1 | |
| 2 | MATERIALIZED | <derived3> | ALL | \N | \N | \N | \N | 734988 | |
| 3 | LATERAL DERIVED | b | ref | pat_id | pat_id | 5 | emr.a.pat_id | 1 | Using where; Using temporary; Using filesort |
+----+-----------------+-------------+--------+---------------+--------------+---------+----------------------------+--------+----------------------------------------------+
感谢任何帮助。 MariaDB 版本:10.4.8。
编辑1:这是pat_id上没有索引的原始表的结构。
CREATE TABLE `vital` (
`pat_id` int(10) unsigned DEFAULT NULL,
`kons_dt` date DEFAULT NULL,
`praxis_id` int(10) unsigned DEFAULT NULL,
`sex` varchar(10) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`doby` smallint(6) DEFAULT NULL,
`age_y` smallint(6) DEFAULT NULL,
`gewicht` double DEFAULT NULL,
`groesse` double DEFAULT NULL,
`bmi` double DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
【问题讨论】:
-
exists 的选择可以减少,因为您不需要该表中的任何数据
-
请提供
SHOW CREATE TABLE vital; -
这会加快查询速度:
INDEX(pat_id, kons_dt),也许会显着。 -
@Rick James:我添加了表格结构和表格行数以及选择。关于加速:谢谢。然而,这不是速度问题,而是向 pat_id 添加索引或组合 pat_id/kons_dt 选择不起作用。如果我删除索引,我会得到预期的结果。这是一个从未遇到过的奇怪行为,因为索引应该加速并且不干扰选择逻辑。
-
您说要添加
INDEX(id),但表格中没有id。请澄清。
标签: mysql indexing mariadb exists