Добрый день.
Ситуация такая. Во первых мы имеем дело с большой таблицей debtors 3000-5000 записей. Мне нужно выбрать из этой таблицы записи только те, которые не входят в записи, получаемые другим запросом.
Сам запрос
1 2 3 4 5 6 7 8 |
$obz_query = "SELECT debtors.*, FROM_UNIXTIME(block_start_date) AS date FROM debtors WHERE users_id NOT IN(SELECT users_id FROM debtors, complete, notes WHERE block_start_date < compl_date AND compl_note = note_id AND n_abon_id = users_id AND is_juridical = 0) AND is_juridical = 0 ORDER BY {$_SESSION['sort']} {$sort_by} LIMIT $start, $num"; |
Complete – база с обработанными debtors.
Notes – заметки к debtors.
Соответственно через notes идет связь между Complete и Notes по compl_note = note_id AND n_abon_id = users_id.
Сейчас в Complete и Notes по 500 записей но они будут расти до 10000 и больше.
Нагрузка на сервер получается дикая.
Как-то можно иначе составить запрос?
Отправился гуглить, наткнулся на пару полезных сайтов:
MySQL.RU – Webboard
sqlinfo.ru
Как ни странно ответили мне именно на втором. Отвечал пользователь deadka, действительно помог, а я получил безценный опыт.
По запросу дал дампы баз и explain запросов. Было предложено добавить индексы.
добавьте составной ключ на deptors.users_id,deptors.is_juridical
123 alter table deptors add index users_id__is_juridical(users_id,is_juridical);И ключ на complete.compl_date
123 alter table `complete` add index compl_date(compl_date);И составной ключ на debtors.is_juridical,debtors.block_start_date
123 alter table debtors add index is_juridical__block_start_date(is_juridical,block_start_date);
Но добавление индексов не дало существенного прироста скорости, а мне нужно почти мгновенное отображение, т.к. в моем проекте запрос происходит после каждой перезагрузки страницы.
Тогда я погуглил еще и нагуглил это:
1
подскажите как составить запрос который бы выводил только те поля из l_client где l_client.l_client_id != b_account.l_client_id?2
123456789 SELECT ..FROMl_clientLEFT JOINb_accountON l_client.l_client_id = b_account.l_client_idWHERE b_account.l_client_id IS NULL;имхо так.
На основе этого примера составили нужный мне запрос.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
SELECT debtors . * , FROM_UNIXTIME( debtors . block_start_date ) AS DATE FROM debtors left join ( SELECT users_id FROM debtors, complete, notes WHERE block_start_date < compl_date AND compl_note = note_id AND n_abon_id = users_id AND is_juridical =0 ) t using(users_id) WHERE t.users_id IS NULL and is_juridical =0 ORDER BY DATE DESC LIMIT 0 , 20 |
Мой запрос с NOT IN – Showing rows 0 – 19 (20 total, Query took 2.8619 sec)
Запрос с LEFT JOIN
Showing rows 0 – 19 (20 total, Query took 0.0606 sec)
Разница на лицо. :)
Все уже внедрено в приложение и операторы могут спокойно обновлять страницу.
В дополнение получил совет, что все же можно успешно использовать not in с базой MariaDB, однако не думаю, что я буду это делать.