MySQL-запрос работает медленно. Помогите оптимизировать это - PullRequest
0 голосов
/ 14 марта 2012

У меня есть этот запрос, который работает довольно хорошо, но становится очень медленным, так как записи увеличиваются в БД. Может кто-нибудь помочь оптимизировать его?

SELECT t1.* 
FROM tbl1 t1 
LEFT JOIN tbl2 t2 on t1.id = t2.tbl1_id AND t2.my_id ='5' 
WHERE t2.tbl1_id IS NULL AND
      t1.userid !='5' AND
      t1.base <= 95 AND
      t1.aloc > 0 AND
      t1.cred > 0 AND
      t1.pause < 1 AND
      t1.admin_se < 1
ORDER by t1.cred+0 DESC 
limit 20");

код для создания таблицы 1

CREATE TABLE `tbl1` (
 `id` int(30) NOT NULL AUTO_INCREMENT,
 `msg` tinytext COLLATE utf8_unicode_ci,
 `userid` varchar(30) COLLATE utf8_unicode_ci DEFAULT NULL,
 `_date` varchar(30) COLLATE utf8_unicode_ci DEFAULT NULL,
 `base` varchar(30) COLLATE utf8_unicode_ci DEFAULT NULL,
 `cred` varchar(30) COLLATE utf8_unicode_ci DEFAULT NULL,
 `aloc` varchar(30) COLLATE utf8_unicode_ci DEFAULT NULL,
 `_expire` varchar(30) COLLATE utf8_unicode_ci DEFAULT NULL,
 `expire_date` varchar(30) COLLATE utf8_unicode_ci DEFAULT NULL,
 `_count` int(30) NOT NULL DEFAULT '0',
 `pause` int(1) NOT NULL DEFAULT '0',
 `src_` varchar(10) COLLATE utf8_unicode_ci DEFAULT NULL,
 `original_url` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
 `short_url` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
 `short_url_code` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
 `scheduler` int(1) NOT NULL DEFAULT '0',
 `admin_se` int(1) NOT NULL DEFAULT '0',
 `autoloadval` varchar(10) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
 `lng` int(30) NOT NULL DEFAULT '1',
 `rinterval` varchar(30) COLLATE utf8_unicode_ci NOT NULL,
 `rcat` int(10) NOT NULL DEFAULT '5',
 PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=11151 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

Код для создания tbl2

CREATE TABLE `tbl2` (
 `tbl2id` int(30) NOT NULL AUTO_INCREMENT,
 `my_id` int(30) DEFAULT NULL,
 `tbl1_msg_id` int(30) DEFAULT NULL,
 `_date` varchar(30) COLLATE utf8_unicode_ci DEFAULT NULL,
 `_type` varchar(5) COLLATE utf8_unicode_ci DEFAULT NULL,
 `fol` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
 `pr_id` int(30) DEFAULT NULL,
 `msg_id` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
 `tracking_id` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
 `val_optimizer` int(1) NOT NULL DEFAULT '0',
 PRIMARY KEY (`tbl2id`)
) ENGINE=MyISAM AUTO_INCREMENT=147014 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

Пожалуйста, примите во внимание, что я новичок в MySQL. Я не понимаю большинство технических терминов.

Я просто хочу, чтобы этот скрипт работал быстро. спасибо

Почему я сделал "заказ по t1.cred + 0" У меня есть значения в поле кредита от 0 до 9999. Я хочу перечислить из самых больших, но что интересно, 5 указано до 10. Не знаю, как поступить с этим

Ответы [ 5 ]

3 голосов
/ 14 марта 2012

Вы добавили индексы к t1.id и t2.tbl1_id и t1.cred+0?

1 голос
/ 14 марта 2012

Попробуйте добавить индекс на ваши ключи.(t1.id и t2.tbl1_id) и в поле group by aswell (t1.cred+0)

Например, использование b-дерева - хорошая идея.

Читатькое-что об индексах

0 голосов
/ 07 ноября 2017

Напишите название каждого столбца, который вы хотите выбрать в своем запросе вместо использования select * from table.

А также создайте индексы и индексы с несколькими столбцами для повышения производительности запросов.Читайте ссылку ниже, чтобы узнать о технике оптимизации запросов MySQL.

https://code.tutsplus.com/tutorials/top-20-mysql-best-practices--net-7855

0 голосов
/ 14 марта 2012

Может быть полезно, если вы покажете нам свой код SQL для создания таблицы, чтобы мы могли видеть, что у вас есть или не проиндексировано.

Медлительность не будет вызвана вашим SQL (обычно) но по твоему индексу твоя таблица.

Джим

0 голосов
/ 14 марта 2012

Попробуйте переписать его с помощью Существует:

SELECT * 
FROM tbl1 t1
WHERE t1.userid !='5'
  AND t1.base <= 95
  AND t1.aloc > 0 
  AND t1.cred > 0
  AND t1.pause < 1    
  AND t1.admin_se < 1
  and not exists (select null from tbl2 t2 where t1.id = t2.tbl1_id AND t2.my_id ='5')
ORDER by t1.cred+0 DESC limit 20;

А какова цель t1.cred + 0? Это сделает индекс на t1.cred непригодным для использования.

EDIT: индексы ускоряют поиск данных. В этом случае вам понадобится индексировать по кредиту, так как это столбец Order by / limit 20. Используйте свой оригинальный запрос (как прокомментировал Марк Баннистер, соединение в основном работает лучше, чем в MySql) Но убедитесь, что вы потеряете + 0 часть, потому что движок sql, вероятно, не сможет использовать индекс.

create index ix_tbl1_cred on tbl1(cred);

Вы будете получать прибыль в основном за счет индексации столбцов равенства, включая цели объединения. Вот индекс столбца tbl2, используемый для соединения tbl2 с tbl1. Теперь MySql не нужно будет читать всю table2 для каждой строки в table1, потому что он проверит индекс на наличие t1.id в t2.tbl1_msg_id

create index ix_tbl2_tbl1_msg_id on tbl2(tbl1_msg_id);

Этого может быть достаточно для этого запроса. Другие столбцы не являются столбцами равенства, поэтому индекс будет иметь меньшее влияние. Я должен знать ваши данные, чтобы предложить другие индексы.

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