Фильтровать большое количество записей в MySQL при использовании INNER JOIN с двумя полями - PullRequest
0 голосов
/ 06 марта 2019

Я работаю над существующей базой данных с миллионами вставок в день. Сам дизайн базы данных довольно плохой, и фильтрация записей занимает огромное количество времени. мы находимся в процессе перемещения этого в кластер ELK, но в то же время я должен отфильтровать некоторые записи для немедленного использования.

У меня есть две таблицы, подобные этой

table - log_1

        datetime         |   id     |   name    |   ip

    2017-01-01 01:01:00  |  12345   |    sam    |     192.168.100.100


table - log_2

         datetime        |   mobile    |   id

    2017-01-01 01:01:00  |  999999999  |  12345   

Мне нужно отфильтровать мои данные, используя ip, а также из log_1 и datetime в log_1 и log_2. Для этого я использую запрос ниже

SELECT log_1.datetime, log_1.id, log_1.name, log_1.ip, log_2,datetime, log_2.mobile, log_2.id
FROM log_1
INNER JOIN log_2
ON log_1.id = log_2.id AND log_1.datetime = log_2.datetime
where log_1.ip = '192.168.100.100'
limit 100

Нет необходимости говорить, что для извлечения результатов с таким большим количеством записей требуется вечность. Есть ли лучший способ, я могу сделать то же самое, не ожидая ответа MySQL в течение длительного времени? Другими словами, как я могу оптимизировать свой запрос к такой большой базе данных.

база данных не является производственной, она предназначена только для аналитики

Ответы [ 2 ]

2 голосов
/ 06 марта 2019

Прежде всего, ваше текущее предложение LIMIT довольно бессмысленно, потому что в запросе нет предложения ORDER BY. Не ясно , какие 100 записей вы хотите сохранить. Итак, вы можете использовать что-то вроде этого:

SELECT
    l1.datetime,
    l1.id,
    l1.name,
    l1.ip,
    l2.datetime,
    l2.mobile,
    l2.id
FROM log_1 l1
INNER JOIN log_2 l2
    ON l1.id = l2.id AND l1.datetime = l2.datetime
WHERE
    l1.ip = '192.168.100.100'
ORDER BY
    l1.datetime DESC
LIMIT 100;

Это вернет 100 самых последних совпадающих записей. Что касается ускорения этого запроса, один из способов как минимум ускорить объединение - добавить следующий индекс в таблицу log_2:

CREATE INDEX idx ON log_2 (datetime, id, mobile);

Предполагая, что MySQL решит использовать этот индекс, это должно значительно ускорить объединение, потому что каждое значение id и datetime можно искать в B-дереве вместо того, чтобы выполнять ручное сканирование всей таблицы. Обратите внимание, что индекс также охватывает столбец mobile, который необходим для выбора.

1 голос
/ 06 марта 2019

Можете ли вы попробовать это: 1. Создайте индекс для обеих таблиц в столбце id, если он еще не создан (это займет время).

  1. Попробуйте создать две временные таблицы log_1_tmp и log_2_tmp с данными, как показано ниже:
Query 1 - insert into log_1_tmp select * from log_1 where log_1.ip = '192.168.100.100'

Query 2 - insert into log_2_tmp select * from log_2 where log_2.ip = '192.168.100.100'
  1. Запустите ваш запрос над двумя таблицами, и здесь вы можете удалить условие where из вашего запроса.

Посмотрите, работает ли это.

...