Медленный зависимый подзапрос - как улучшить производительность? - PullRequest
2 голосов
/ 19 июня 2011

В моей базе данных есть транзакции с именами таблиц, в которых содержится 20000 записей. Когда я запускаю этот запрос

SELECT T1.* FROM transactions AS T1
WHERE T1.ppno IN 
  (SELECT T2.PPNO FROM transactions AS T2 
   WHERE T2.ppno = T1.ppno 
   HAVING COUNT(T2.ppno) = $doublescount) 
 ORDER BY T1.ppno,T1.numb

для запуска требуется не менее 3 минут. Как ускорить этот запрос?

Редактировать

show create table transactions возвращается как

CREATE TABLE `transactions` (
  `eidx` int(10) unsigned NOT NULL,
  `numb` int(10) unsigned NOT NULL,
  `date` date NOT NULL,
  `time` varchar(45) NOT NULL,
  `name` varchar(45) NOT NULL,
  `add1` varchar(45) NOT NULL,
  `add2` varchar(45) NOT NULL,
  `city` varchar(45) NOT NULL,
  `phno` varchar(45) NOT NULL,
  `nati` varchar(45) NOT NULL,
  `ppno` varchar(45) NOT NULL,
  `cuam` varchar(45) NOT NULL,
  `tcam` varchar(45) NOT NULL,
  `valu` varchar(45) NOT NULL,
  `srch` varchar(45) NOT NULL,
  `stax` varchar(45) NOT NULL,
  `taxp` varchar(45) NOT NULL,
  `roun` varchar(45) NOT NULL,
  `amnt` varchar(45) NOT NULL,
  `encd` varchar(45) NOT NULL,
  `mocd` varchar(45) NOT NULL,
  `endt` varchar(45) NOT NULL,
  `modt` varchar(45) NOT NULL,
  `sflg` varchar(5) NOT NULL,
  `category` varchar(45) NOT NULL DEFAULT 'NA',
  `branch` varchar(10) NOT NULL,
  PRIMARY KEY (`numb`,`branch`,`date`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=FIXED

Ответы [ 4 ]

5 голосов
/ 19 июня 2011

Вместо использования условия IN используйте LEFT JOIN NULL

http://explainextended.com/2010/05/27/left-join-is-null-vs-not-in-vs-not-exists-nullable-columns/

3 голосов
/ 19 июня 2011

Подзапросы медленные.Используйте JOIN для временной таблицы, содержащей все ppno, которые удовлетворяют условию.

SELECT T1.* FROM transactions AS T1 
JOIN (SELECT DISTINCT T2.PPNO FROM transactions AS T2 HAVING COUNT(T2.ppno) = $doublescount) AS temp ON temp.PPNO=T1.ppno
ORDER BY T1.ppno,T1.numb
2 голосов
/ 29 сентября 2011

измените SELECT T1.* FROM transactions AS T1, чтобы он выбирал только нужные вам столбцы, например, SELECT T1.ppno, T1.name FROM transactions as T1, а затем использовал метод соединения, предоставленный Гербеном.

при использовании SELECT * система базы данных должна работатькакие столбцы находятся в базе данных, а затем выделяют память для каждого столбца и строки - довольно много фоновой работы перед выполнением запроса.Используя именованные столбцы, системе баз данных нужно только проверять эти столбцы - меньше фоновой работы перед выполнением запроса.

Если для выполнения вашего запроса требуется 3 минуты, возможно, у вас происходит декартово соединение, где результирующий наборпотенциально может столкнуться с миллионами.Метод соединения gerben предотвращает это, создавая временную таблицу, состоящую из результата подзапроса, добавленного к основной таблице, основной запрос выполняется для этой временной таблицы, чтобы получить гораздо меньший набор результатов.

0 голосов
/ 19 июня 2011

Если узким местом является база данных, вы также можете не указывать ORDER BY и выполнять упорядочивание в приложении вместо базы данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...