Ad Widget

Collapse

Оптимизация запроса mysql

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • turboon
    Member
    • Sep 2010
    • 93

    #1

    Оптимизация запроса mysql

    Доброе время суток.
    Вот мои запросы:
    1. "SELECT i.itemid FROM items i WHERE i.key_ = 'backup.ntbackup.data'" - возвращает 6 значений : 58039, 58040, 58041, 58042, 58043, 58044
    2. "SELECT * FROM history_text ht WHERE ht.itemid IN ( SELECT i.itemid FROM items i WHERE i.key_ = 'backup.ntbackup.data' ) - надолго задумывается
    3. Но "SELECT * FROM history_text ht WHERE ht.itemid IN ( 58039, 58040, 58041, 58042, 58043, 58044 )" - отрабатывает мгновенно

    Хотел бы использовать в программе запрос №2, но вопрос в том, как его оптимизировать.
    Подозреваю, что mysql для каждой строчки history_text выполняет вложенный запрос. Есть ли способы заставить его исполнить вложенный запрос 1 раз, и использовать результаты в переборе?
  • zalex_ua
    Senior Member
    Zabbix Certified Trainer
    Zabbix Certified SpecialistZabbix Certified Professional
    • Oct 2009
    • 1286

    #2
    3. выполняется мгновенно потому что 2. уже был выполнен и история уже в кеше (памяти)
    Не должно быть проблем со вложенностью запросаов просто выборка из истории это тяжелая задача.

    Comment

    • turboon
      Member
      • Sep 2010
      • 93

      #3
      Увы, все это не совсем так..
      1,2,3 в моем посте - это не порядок выполнения, а нумерация для удобства.

      Вот пример попроще:

      Code:
      SELECT * FROM history_text ht WHERE ht.itemid IN ( 58039 )
      - выполняется 0.002 секунды

      Code:
      SELECT * FROM history_text ht WHERE ht.itemid IN ( select itemid from items where itemid =  58039 )
      - 14 секунд

      Можно ли это пофиксить?

      Comment

      • dotneft
        Senior Member
        • Nov 2008
        • 699

        #4
        Попробуйте этот

        Code:
        SELECT * FROM history_text ht JOIN items i USING(itemid) WHERE i.itemid IN (58039);

        Comment

        • turboon
          Member
          • Sep 2010
          • 93

          #5
          Да, ваш запрос работает быстро.
          Однако нужный мне:
          Code:
          SELECT * FROM history_text ht JOIN items i USING(itemid) WHERE i.key_ = 'backup.ntbackup.data'
          - думает 40 секунд...

          Comment

          • dotneft
            Senior Member
            • Nov 2008
            • 699

            #6
            Эм... Логично. Покажите вывод этого запросы с explain.

            А вообще выполняйте в два запроса, если не ошибаюсь то explain будет плачевным.

            Comment

            • noname
              Senior Member
              • Jan 2008
              • 120

              #7
              Вот для публики explain-ы, там и правда все грустно (я на похожем примере взял):

              mysql> explain select * from history_uint h where h.itemid in (SELECT i.itemid FROM items i WHERE i.key_ = 'system.localtime');
              +----+--------------------+-------+-----------------+---------------+---------+---------+------+----------+-------------+
              | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
              +----+--------------------+-------+-----------------+---------------+---------+---------+------+----------+-------------+
              | 1 | PRIMARY | h | ALL | NULL | NULL | NULL | NULL | 54564440 | Using where |
              | 2 | DEPENDENT SUBQUERY | i | unique_subquery | PRIMARY | PRIMARY | 8 | func | 1 | Using where |
              +----+--------------------+-------+-----------------+---------------+---------+---------+------+----------+-------------+
              2 rows in set (0.00 sec)

              В то время, как:

              mysql> explain select * from history_uint h where h.itemid in (38,33229);
              +----+-------------+-------+-------+----------------+----------------+---------+------+------+-------------+
              | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
              +----+-------------+-------+-------+----------------+----------------+---------+------+------+-------------+
              | 1 | SIMPLE | h | range | history_uint_1 | history_uint_1 | 8 | NULL | 2681 | Using where |
              +----+-------------+-------+-------+----------------+----------------+---------+------+------+-------------+
              1 row in set (0.00 sec)

              А вот, что говорится на сайте mysql:
              http://dev.mysql.com/doc/refman/5.0/...trictions.html

              нужная вырезка (касающаяся вложенных select-ов):
              If the inner and outer queries return M and N rows, respectively, the execution time becomes on the order of O(M×N), rather than O(M+N) as it would be for an uncorrelated subquery.

              вывод:
              используйте два запроса. Сначала сформируйте список итемов, а потом его уже в IN (...)

              Comment

              • turboon
                Member
                • Sep 2010
                • 93

                #8
                сДа, поэкспериментировал с explain, и в итоге сделал в 2 запроса..
                Некрасиво, но зато быстро
                Спасибо!

                Comment

                • dotneft
                  Senior Member
                  • Nov 2008
                  • 699

                  #9
                  Прошу прощения, а зачем вам вообще доставать эти данные через sql?

                  Comment

                  • Makc666
                    Junior Member
                    • Oct 2012
                    • 12

                    #10
                    Originally posted by turboon
                    Хотел бы использовать в программе запрос №2, но вопрос в том, как его оптимизировать.
                    Какая у Вас версия базы данных, только точно...

                    Comment

                    • turboon
                      Member
                      • Sep 2010
                      • 93

                      #11
                      Прошу прощения, а зачем вам вообще доставать эти данные через sql?
                      Надо добавить хинт к некоторым колонкам в обзоре данных.

                      Какая у Вас версия базы данных, только точно...
                      Code:
                      mysql -V
                      mysql  Ver 14.14 Distrib 5.1.61, for redhat-linux-gnu (x86_64) using readline 5.1

                      Comment

                      Working...