powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Оптимизация sql запроса
23 сообщений из 23, страница 1 из 1
Оптимизация sql запроса
    #38776384
uniken1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте.

Я периодически получают статистику из базы мониторига по всем сетевым интерфесам, для того чтобы понять которые из них за всю историю ни разу не были в "апе", вот таким запросом
Код: sql
1.
2.
3.
4.
5.
6.
7.
SELECT id.hostid, MIN(hu.value) , id.key_
FROM `history_uint` AS hu JOIN (SELECT `itemid`,`hostid`,`key_` FROM `items` where `key_` LIKE "ifOperStatus[GigabitEthernet%]") AS id
WHERE hu.itemid = id.itemid GROUP BY hu.itemid ORDER By id.hostid, id.key_
INTO OUTFILE '/tmp/listports.csv'
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\n'


если MIN(hu.value) = 2 тогда интерфейс ни разу не был в "апе"

У меня такой запрос выполняется около 20 часов.
Можно ли как-то оптимизировать запрос, чтобы он выполнялся быстрее(в таблице history_uint около 250 млн записей)?
...
Рейтинг: 0 / 0
Оптимизация sql запроса
    #38776405
Фотография javajdbc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uniken1,

1. не стесняйтесь придавать запросам читаемый вид

SELECT id.hostid, MIN(hu.value) , id.key_
FROM `history_uint` AS hu
JOIN
(
SELECT `itemid`,`hostid`,`key_`
FROM `items` where `key_`
LIKE "ifOperStatus[GigabitEthernet%]"
) AS id
WHERE hu.itemid = id.itemid
GROUP BY hu.itemid
ORDER By id.hostid, id.key_
...
Рейтинг: 0 / 0
Оптимизация sql запроса
    #38776416
Фотография javajdbc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2. для оптимизации лучше разобратся по отдельности без ИНТО ФИЛЕ.

3. Можно отдельно попытатся оптимизаировать
SELECT `itemid`,`hostid`,`key_`
FROM `items` where `key_`
LIKE "ifOperStatus[GigabitEthernet%]"

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

5. Для начала почитайте про, и выполните EXPLAIN
для всего запроса (без ИНТО ФИЛЕ) и отдельно для
подзапроса. Если сможете переписать без подселекта,
дайте и его ЕХПЛАИН.
...
Рейтинг: 0 / 0
Оптимизация sql запроса
    #38776447
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
1) Измените LIKE на INSTR, и максимально укоротите строку поиска.
2) Сколько записей возвращает подзапрос
Код: sql
1.
2.
3.
SELECT `itemid`,`hostid`,`key_` 
FROM `items` 
WHERE `key_` LIKE 'ifOperStatus[GigabitEthernet%]'


Сколько записей возвращает запрос
Код: sql
1.
2.
3.
SELECT id.hostid, MIN(hu.value)
FROM `history_uint` AS hu
GROUP BY hu.itemid


И сколько записей в итоговом результате.
3) Нафига нужна конечная сортировка?
...
Рейтинг: 0 / 0
Оптимизация sql запроса
    #38776500
alex564657498765453
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
тут сразу встаёт вопрос с точки зрения логики.

есть 10000 сетевых интерфейсов...
есть 10 млн записей логов.
мы за 20 часов получили
100 интерфейсов
с айди скажем 1,2,3 .... ,100
которые за всю историю ни разу небыли в апе.

вопрос...

через две недели, каковы шансы, что интерфейс с айди 200 ниразу небыл в апе за всю историю???
...
Рейтинг: 0 / 0
Оптимизация sql запроса
    #38776861
uniken1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
javajdbc4. Можно переписать оптимизировать запрос без подселекта.

Я не знаю как это сделать.

javajdbc5. Для начала почитайте про, и выполните EXPLAIN
для всего запроса (без ИНТО ФИЛЕ) и отдельно для
подзапроса. Если сможете переписать без подселекта,
дайте и его ЕХПЛАИН.

Для подселекта можно сделать, а для полного запроса запущу, но ждать придется сутки.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
mysql> explain SELECT `itemid`,`hostid`,`key_` FROM `items` where `key_` LIKE "ifOperStatus[GigabitEthernet%]";
+----+-------------+-------+-------+---------------+---------+---------+------+-------+--------------------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows  | Extra                    |
+----+-------------+-------+-------+---------------+---------+---------+------+-------+--------------------------+
|  1 | SIMPLE      | items | index | NULL          | items_1 | 775     | NULL | 16712 | Using where; Using index |
+----+-------------+-------+-------+---------------+---------+---------+------+-------+--------------------------+
1 row in set (0.00 sec)


Akina1) Измените LIKE на INSTR, и максимально укоротите строку поиска.
Попробую.

Akina2) Сколько записей возвращает подзапрос
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
mysql> SELECT count(0) FROM `items` where `key_` LIKE "ifOperStatus[GigabitEthernet%]";
+----------+
| count(0) |
+----------+
|     1650 |
+----------+
1 row in set (0.04 sec)

AkinaСколько записей возвращает запрос
Расчетно около 35 млн. записей.

Akina3) Нафига нужна конечная сортировка?
Это правда, сортировка тут не нужна

alex564657498765453через две недели, каковы шансы, что интерфейс с айди 200 ниразу небыл в апе за всю историю???
Для этого и делается запрос с некоторой периодичностью.
А на счет за всю историю, тут надо пояснить.
База разбита ежедневным партиционированием. Партиции старше 30 дней удаляются. Поэтому автоматически "за всю историю"="за последние 30 дней"

Из того что я сам пробовал понять что тормозит, то запрос
Код: sql
1.
2.
3.
SELECT MIN(hu.value)
FROM `history_uint` AS hu
WHERE hu.itemid=1012


Выполняется 19 часов.
...
Рейтинг: 0 / 0
Оптимизация sql запроса
    #38776869
uniken1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
javajdbc5. Для начала почитайте про, и выполните EXPLAIN
для всего запроса

А запрос быстро выполнился
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
mysql> EXPLAIN SELECT id.hostid, MIN(hu.value) , id.key_
    -> FROM `history_uint` AS hu JOIN (SELECT `itemid`,`hostid`,`key_` FROM `items` where `key_` LIKE "ifOperStatus[GigabitEthernet%]") AS id
    -> WHERE hu.itemid = id.itemid GROUP BY hu.itemid ORDER By id.hostid, id.key_;
+----+-------------+------------+-------+----------------+----------------+---------+-----------+-------+---------------------------------+
| id | select_type | table      | type  | possible_keys  | key            | key_len | ref       | rows  | Extra                           |
+----+-------------+------------+-------+----------------+----------------+---------+-----------+-------+---------------------------------+
|  1 | PRIMARY     | <derived2> | ALL   | NULL           | NULL           | NULL    | NULL      |  1650 | Using temporary; Using filesort |
|  1 | PRIMARY     | hu         | ref   | history_uint_1 | history_uint_1 | 8       | id.itemid |   404 |                                 |
|  2 | DERIVED     | items      | index | NULL           | items_1        | 775     | NULL      | 16712 | Using where; Using index        |
+----+-------------+------------+-------+----------------+----------------+---------+-----------+-------+---------------------------------+
3 rows in set (0.02 sec)
...
Рейтинг: 0 / 0
Оптимизация sql запроса
    #38776982
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uniken1,

Что-то так никто и не заметил...

Код: plaintext
1.
SELECT  id.hostid, id.key_ , MIN(hu.value) 


Код: plaintext
 GROUP BY  hu.itemid 

Т.е. группируем мы по Item, а хотим видеть Host и Key ?

В нормальных вменяемых запросах выделенные куски должны совпадать . У тебя они разные.
...
Рейтинг: 0 / 0
Оптимизация sql запроса
    #38777042
uniken1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MasterZivuniken1,

Что-то так никто и не заметил...

Код: plaintext
1.
SELECT  id.hostid, id.key_ , MIN(hu.value) 


Код: plaintext
 GROUP BY  hu.itemid 

Т.е. группируем мы по Item, а хотим видеть Host и Key ?

В нормальных вменяемых запросах выделенные куски должны совпадать . У тебя они разные.
Не совсем понял, а что не так? В выводе результата мне не нужен параметр по которому идет группировка...
...
Рейтинг: 0 / 0
Оптимизация sql запроса
    #38777074
tanglir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uniken1а что не так? 13173672
...
Рейтинг: 0 / 0
Оптимизация sql запроса
    #38777272
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uniken1MasterZivuniken1,

Что-то так никто и не заметил...

Код: plaintext
1.
SELECT  id.hostid, id.key_ , MIN(hu.value) 


Код: plaintext
 GROUP BY  hu.itemid 

Т.е. группируем мы по Item, а хотим видеть Host и Key ?

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

"Не так" -- логика запроса идиотская. Что он тебе будет возвращать -- совершенно не понятно. Если тебя это устраивает, можешь и дальше заниматься оптимизацией запроса, который возвращает хрень.
...
Рейтинг: 0 / 0
Оптимизация sql запроса
    #38777389
uniken1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MasterZiv"Не так" -- логика запроса идиотская. Что он тебе будет возвращать -- совершенно не понятно. Если тебя это устраивает, можешь и дальше заниматься оптимизацией запроса, который возвращает хрень.
Я не понял почему. Можете объяснить на примере?
Этот запрос возвращает точно правильные данные, так как я по его результатам "глазками" проверяют соответствующие порты на коммутаторах, и никогда не верных данных не было.
...
Рейтинг: 0 / 0
Оптимизация sql запроса
    #38777400
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uniken1Я не понял почему. Можете объяснить на примере?
Патамучта...
uniken1
Код: sql
1.
2.
3.
4.
SELECT id.hostid, MIN(hu.value) , id.key_
-- ...
GROUP BY hu.itemid
-- ...


Допустим, в данных после джойна, но до групбай, есть вот такие строки
hostidkey_111122
После групбай этих записей в выходном наборе будет hostid=1? это очевидно, а вот что должно, по твоему мнению, быть в key_ ? 11? 22? И, главное, почему...
Думай.
...
Рейтинг: 0 / 0
Оптимизация sql запроса
    #38777461
uniken1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
AkinaДумай.
Думаю:
У меня есть таблица history_uint AS hu из которой я хочу получить данные.
В селекте я указываю поля которые мне нужны в выводе, и не указываю которые не нужны.
И если я выполняю group или order на полях которые я не указал в выводе, они же никуда не деваются, выборка же идет по всей таблице hu, и не зависимо при'join'ились к этой таблице данные из другой таблицы или нет.
Ваш пример мне кажется не совсем корректным, так как после join'а hu.itemid никуда не денется из промежуточной таблицы по нему нормально отрабатывает group by.
Я не прав?
...
Рейтинг: 0 / 0
Оптимизация sql запроса
    #38777464
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uniken1MasterZiv"Не так" -- логика запроса идиотская. Что он тебе будет возвращать -- совершенно не понятно. Если тебя это устраивает, можешь и дальше заниматься оптимизацией запроса, который возвращает хрень.
Я не понял почему. Можете объяснить на примере?
Этот запрос возвращает точно правильные данные, так как я по его результатам "глазками" проверяют соответствующие порты на коммутаторах, и никогда не верных данных не было.

Почти во всех нормальных СУБД (и даже в некоторых ненормальных) ЗАПРЕЩЕНО включать в список вывода
(SELECT list, список полей и выражений в запросе) поля таблиц, которые не включены во фразу GROUP BY или не
находятся под агрегатными функциями.

И это вполне логично -- по одним полям ты группируешь, другие поля ты суммируешь, подсчитываешь и так далее.
Если ты с полем не делаешь ни то, ни другое, то какое значение туда попадёт -- не понятно , потому что в разных записах значения этих полей могут быть разными. Чтобы чётко определить семантику выполнения SELECT...GROUP BY, такое запрещено,
и даже, если я не ошибаюсь, в стандарте ANSI SQL.

Но некоторые особо умные (в том числе и MySQL) СУБД допускают такие запросы, при этом явно декларируют, как будет работать такой запрос. В MySQL это тоже задокументировано -- для полей, не входящих в GROUP BY и AGGREGATE FUNCTION будут использоваться любые произвольные значения из имеющихся в таблице.
...
Рейтинг: 0 / 0
Оптимизация sql запроса
    #38777466
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivНо некоторые особо умные (в том числе и MySQL) СУБД допускают такие запросы, при этом явно декларируют, как будет работать такой запрос. В MySQL это тоже задокументировано -- для полей, не входящих в GROUP BY и AGGREGATE FUNCTION будут использоваться любые произвольные значения из имеющихся в таблице.

http://dev.mysql.com/doc/refman/5.7/en/group-by-extensions.html
...
Рейтинг: 0 / 0
Оптимизация sql запроса
    #38777975
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uniken1Ваш пример мне кажется не совсем корректным, так как после join'а hu.itemid никуда не денется из промежуточной таблицы по нему нормально отрабатывает group by.
Я не прав?
Хуже. Вы не думаете.

Покажите первый десяток строк своего запроса, убрав из него MIN и GROUP BY.
Убедитесь, что мой пример корректен.
Ответьте на мой вопрос.
...
Рейтинг: 0 / 0
Оптимизация sql запроса
    #38778416
alex564657498765453
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вообщем вопросы к ТС

1. зачем надо select from t1 join (select from t2) вместо select from t1 join t2

2. зачем select a,c,b order by a,b >> csv
вместо select a,b,c >> csv && sort csv
...
Рейтинг: 0 / 0
Оптимизация sql запроса
    #38786260
uniken1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Я прочитал статью, теперь понял, к чему вы все это говорили, и почему в моем запросе это не влияло на результат.

Но все-таки это ни как не относится а к производительности запроса.
Я попробовал оставить только одну часть запроса. И такой запрос не выполнился за сутки:
Код: sql
1.
SELECT hu.itemid ,MIN(hu.value) as minVal FROM `history_uint` AS hu GROUP BY hu.itemid;


Explain:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
mysql> explain  SELECT hu.itemid ,MIN(hu.value) as minVal FROM `history_uint` AS hu GROUP BY hu.itemid\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: hu
         type: index
possible_keys: NULL
          key: history_uint_1
      key_len: 12
          ref: NULL
         rows: 218513219
        Extra: 
1 row in set (0.00 sec)



Есть какие-то варианты увеличить скорость?
...
Рейтинг: 0 / 0
Оптимизация sql запроса
    #38786706
Фотография javajdbc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uniken1,

11. покажите все индексы на таблице (таблицах)

SHOW CREATE TABLE abc;


12. добавьте двойной индекс (itemid ,value).

Отработайте идею на средней базе -- ибо
на громадной базе создание индекса может быть долгим.

После создания индекса сделайте еше один ЕХПЛАИН
и замерьте скорость.


12. Если запрос надо гонять несколько раз, то лучше создать
промежуточную таблицу с сборной статистикой по дням (или неделям).
например, примерно такую:

itemid, min_val, max_val, avg_val, event_count,time_start, time_end

Затем каждый день добавлять только недавние агрегаты.
...
Рейтинг: 0 / 0
Оптимизация sql запроса
    #38786736
uniken1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сама база данный принадлежит мониторинговому приложению (если имеет значение то это zabbix).
И можно ли что-то менять в схеме я точно не знаю.
Добавление индекса не может негативно повлиять на работу в целом.
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
mysql> show create table history_uint\G
*************************** 1. row ***************************
       Table: history_uint
Create Table: CREATE TABLE `history_uint` (
  `itemid` bigint(20) unsigned NOT NULL,
  `clock` int(11) NOT NULL DEFAULT '0',
  `value` bigint(20) unsigned NOT NULL DEFAULT '0',
  `ns` int(11) NOT NULL DEFAULT '0',
  KEY `history_uint_1` (`itemid`,`clock`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*!50100 PARTITION BY RANGE ( clock)
(PARTITION p2014_09_24 VALUES LESS THAN (1411588800) ENGINE = InnoDB,
 PARTITION p2014_09_25 VALUES LESS THAN (1411675200) ENGINE = InnoDB,
 PARTITION p2014_09_26 VALUES LESS THAN (1411761600) ENGINE = InnoDB,
 PARTITION p2014_09_27 VALUES LESS THAN (1411848000) ENGINE = InnoDB,
 PARTITION p2014_09_28 VALUES LESS THAN (1411934400) ENGINE = InnoDB,
 PARTITION p2014_09_29 VALUES LESS THAN (1412020800) ENGINE = InnoDB,
 PARTITION p2014_09_30 VALUES LESS THAN (1412107200) ENGINE = InnoDB,
 PARTITION p2014_10_01 VALUES LESS THAN (1412193600) ENGINE = InnoDB,
 PARTITION p2014_10_02 VALUES LESS THAN (1412280000) ENGINE = InnoDB,
 PARTITION p2014_10_04 VALUES LESS THAN (1412452800) ENGINE = InnoDB,
 PARTITION p2014_10_05 VALUES LESS THAN (1412539200) ENGINE = InnoDB,
 PARTITION p2014_10_06 VALUES LESS THAN (1412625600) ENGINE = InnoDB,
 PARTITION p2014_10_07 VALUES LESS THAN (1412712000) ENGINE = InnoDB,
 PARTITION p2014_10_08 VALUES LESS THAN (1412798400) ENGINE = InnoDB,
 PARTITION p2014_10_09 VALUES LESS THAN (1412884800) ENGINE = InnoDB,
 PARTITION p2014_10_10 VALUES LESS THAN (1412971200) ENGINE = InnoDB,
 PARTITION p2014_10_11 VALUES LESS THAN (1413057600) ENGINE = InnoDB,
 PARTITION p2014_10_12 VALUES LESS THAN (1413144000) ENGINE = InnoDB,
 PARTITION p2014_10_13 VALUES LESS THAN (1413230400) ENGINE = InnoDB,
 PARTITION p2014_10_14 VALUES LESS THAN (1413316800) ENGINE = InnoDB,
 PARTITION p2014_10_15 VALUES LESS THAN (1413403200) ENGINE = InnoDB,
 PARTITION p2014_10_16 VALUES LESS THAN (1413489600) ENGINE = InnoDB,
 PARTITION p2014_10_18 VALUES LESS THAN (1413662400) ENGINE = InnoDB,
 PARTITION p2014_10_19 VALUES LESS THAN (1413748800) ENGINE = InnoDB,
 PARTITION p2014_10_20 VALUES LESS THAN (1413835200) ENGINE = InnoDB,
 PARTITION p2014_10_21 VALUES LESS THAN (1413921600) ENGINE = InnoDB,
 PARTITION p2014_10_22 VALUES LESS THAN (1414008000) ENGINE = InnoDB,
 PARTITION p2014_10_23 VALUES LESS THAN (1414094400) ENGINE = InnoDB,
 PARTITION p2014_10_24 VALUES LESS THAN (1414180800) ENGINE = InnoDB,
 PARTITION p2014_10_25 VALUES LESS THAN (1414267200) ENGINE = InnoDB) */
1 row in set (0.00 sec)

mysql> show columns from history_uint;
+--------+---------------------+------+-----+---------+-------+
| Field  | Type                | Null | Key | Default | Extra |
+--------+---------------------+------+-----+---------+-------+
| itemid | bigint(20) unsigned | NO   | MUL | NULL    |       |
| clock  | int(11)             | NO   |     | 0       |       |
| value  | bigint(20) unsigned | NO   |     | 0       |       |
| ns     | int(11)             | NO   |     | 0       |       |
+--------+---------------------+------+-----+---------+-------+
4 rows in set (0.01 sec)




Нет, запрос я делаю вручную, не очень часто (может раз в месяц).
...
Рейтинг: 0 / 0
Оптимизация sql запроса
    #38786744
uniken1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добавление индекса не может негативно повлиять на работу в целом? (это был вопрос))
...
Рейтинг: 0 / 0
Оптимизация sql запроса
    #38786778
Фотография javajdbc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uniken1Добавление индекса не может негативно повлиять на работу в целом? (это был вопрос))

На каждый индекс система должна тратить какието
дополнительные наносекунды при вставке записи.
Если он сработает -- то ускорит выборку на пару-тройку порядков.
Ну и само постриение может занять много времени.

По запросу - у вас натурально просится
сделать (пред-) агрегацию по дням.
Идея в том чтоб посчитать каждый ден- ОДИН раз,
сохранить и использовать только пред-агрегаты для
больших запросов.
...
Рейтинг: 0 / 0
23 сообщений из 23, страница 1 из 1
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Оптимизация sql запроса
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]