Nano Hash - криптовалюты, майнинг, программирование

MariaDB: нет выбора с использованием EXISTS, если столбец имеет индекс

Впервые я столкнулся с проблемой использования EXISTS, которую я не понимаю. У меня есть таблица с идентификатором пациента и датой консультации, и я пытаюсь выбрать тех пациентов, у которых есть несколько записей с одной и той же датой консультации:

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

  • выбор существующих может быть уменьшен, потому что вам не нужны данные из этой таблицы 03.08.2020
  • Пожалуйста, предоставьте SHOW CREATE TABLE vital; 03.08.2020
  • Это ускорит запрос: INDEX(pat_id, kons_dt), возможно, значительно. 03.08.2020
  • @Rick James: я добавил структуру таблицы и количество строк таблицы и выбор. По поводу ускорения: спасибо. Тем не менее, дело не в скорости, а в том, что добавление индекса к pat_id или комбинированное pat_id/kons_dt выборки не работает. Если я удалю индекс, я получу ожидаемый результат. Это странное поведение, с которым никогда не сталкивались, потому что индекс должен ускоряться и не вмешиваться в логику выбора. 04.08.2020
  • Вы говорите о добавлении INDEX(id), а id в таблице нет. Просьба уточнить. 04.08.2020
  • @Rick James: Спасибо и извините, моя вина. Следует писать pat_id, а не id. Я поправил в своем вопросе. Запрос был сделан правильно с pat_id (иначе выдавало бы ошибку). 05.08.2020

Ответы:


1

У тебя есть загадка. Если вы можете создать небольшой набор данных, который показывает проблему (и не содержит конфиденциальной информации), отправьте отчет об ошибке.

А пока попробуйте это:

SELECT  a.*
    FROM ( SELECT  DISTINCT pat_id
            FROM ( SELECT  pat_id, kons_dt
                    FROM  emr.vital b
                    GROUP BY  pat_id, kons_dt
                    HAVING  COUNT(*) > 1 
                 ) b
         ) c
    JOIN  emr.vital a USING(pat_id)
    WHERE  a.pat_id = c.pat_id ;

и есть INDEX(pat_id, kons_dt)

05.08.2020
Новые материалы

Кластеризация: более глубокий взгляд
Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

Как написать эффективное резюме
Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..