Mysql бинарное дерево выбора запросов оптимизации - PullRequest
0 голосов
/ 14 июня 2019

У меня есть таблица счетов. при каждом создании учетной записи я помещаю идентификатор treeRight и идентификатор treeLeft в таблицу account_device_tree.

Теперь у меня более 10 миллионов учетных записей под первым родительским аккаунтом. когда я выбираю все подаккауты, выполнение занимает больше минуты.

мой запрос приведен ниже

select * 
FROM
    accounts acc 
        JOIN
    account_device_tree ON acc.tree_id = account_device_tree.tree_id
WHERE
(acc.account_id = 1 OR (account_device_tree.tree_left >= 1 AND account_device_tree.tree_right <= 748534))

Мне нужно максимально оптимизировать.

схема account_device_tree

CREATE TABLE `account_device_tree` (
  `tree_id` int(11) NOT NULL AUTO_INCREMENT,
  `tree_left` int(11) NOT NULL,
  `tree_right` int(11) NOT NULL,
  PRIMARY KEY (`tree_id`),
  KEY `tree_left` (`tree_left`),
  KEY `tree_right` (`tree_right`)
) ENGINE=InnoDB AUTO_INCREMENT=388173 DEFAULT CHARSET=latin1

Схема таблицы счетов

 CREATE TABLE `accounts` (
  `account_id` int(11) NOT NULL AUTO_INCREMENT,
  `parent_id` int(11) NOT NULL,
  `name` varchar(64) NOT NULL,
  `tree_id` int(11) NOT NULL,
  PRIMARY KEY (`account_id`),
  UNIQUE KEY `tree_id` (`tree_id`),
  KEY `name` (`name`),
  KEY `idx_parent_id` (`parent_id`)
) ENGINE=InnoDB AUTO_INCREMENT=389739 DEFAULT CHARSET=latin1

1 Ответ

1 голос
/ 14 июня 2019

Трудно что-то предложить без структур таблиц и плана запроса. Но переписывание запроса в UNION ALL вместо использования OR имеет тенденцию оптимизировать лучшую версию, если в таблице указаны правильные индексы.

select * 
FROM
    accounts acc 
        JOIN
    account_user_device_tree ON acc.tree_id = account_user_device_tree.tree_id
WHERE
  acc.account_id = 1 

UNION ALL

select * 
FROM
    accounts acc 
        JOIN
    account_user_device_tree ON acc.tree_id = account_user_device_tree.tree_id
WHERE
   account_user_device_tree.tree_left >= 1
 AND
  account_user_device_tree.tree_right <= 748534
...