SQLinfo.ru - Все о MySQL Webew.ru: теория и практика веб-технологий

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 11.11.2012 16:41:47

animegirl
Активист
Зарегистрирован: 28.07.2011
Сообщений: 288

Ускорит или замедлит?

Таблицы


CREATE TABLE IF NOT EXISTS `tech_regions_names` (
  `region_id` mediumint(8) unsigned NOT NULL,
  `country_id` smallint(5) unsigned NOT NULL,
  `region_language` varchar(7) COLLATE utf8_unicode_ci NOT NULL,
  `region_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY (`region_id`,`region_language`),
  KEY `region_id` (`region_id`),
  KEY `region_name` (`region_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

CREATE TABLE IF NOT EXISTS `tech_regions_positions` (
  `region_id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
  `latitude_top` double(9,6) NOT NULL,
  `latitude_bottom` double(9,6) NOT NULL,
  `longitude_left` double(9,6) NOT NULL,
  `longitude_right` double(9,6) NOT NULL,
  PRIMARY KEY (`region_id`),
  KEY `region_GCS` (`latitude_top`,`latitude_bottom`,`longitude_left`,`longitude_right`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;
 


Запрос вариант первый:

        SELECT `tech_regions_positions`.`region_id`,`tech_regions_names`.`region_language`,IF(`region_language`='ur',0,IF(`region_language`='en',1,IF(`region_language`='cn',2,IF(`region_language`='es',3,IF(`region_language`='jp',4,IF(`region_language`='pt',5,IF(`region_language`='de',6,IF(`region_language`='fr',7,IF(`region_language`='ru',8,9))))))))) `language_priority`
        FROM `".$db_name."`.`tech_regions_names`,`".$db_name."`.`tech_regions_positions`
        WHERE `tech_regions_names`.`region_id`=`tech_regions_positions`.`region_id`
            AND
                (
                (
                (".waysql_secure($_POST['ML'])."<=`tech_regions_positions`.`longitude_left` AND `tech_regions_positions`.`longitude_left`<=".waysql_secure($_POST['MR']).")
                OR
                (".waysql_secure($_POST['ML'])."<=`tech_regions_positions`.`longitude_right` AND `tech_regions_positions`.`longitude_right`<=".waysql_secure($_POST['MR']).")
                )
                AND
                (
                (".waysql_secure($_POST['MT']).">=`tech_regions_positions`.`latitude_top` AND `tech_regions_positions`.`latitude_top`>=".waysql_secure($_POST['MB']).")
                OR
                (".waysql_secure($_POST['MT']).">=`tech_regions_positions`.`latitude_bottom` AND `tech_regions_positions`.`latitude_bottom`>=".waysql_secure($_POST['MB']).")
                )
                )
 

Запрос вариант другой:

        SELECT `tech_regions_positions`.`region_id`,`tech_regions_names`.`region_language`,IF(`region_language`='ur',0,IF(`region_language`='en',1,IF(`region_language`='cn',2,IF(`region_language`='es',3,IF(`region_language`='jp',4,IF(`region_language`='pt',5,IF(`region_language`='de',6,IF(`region_language`='fr',7,IF(`region_language`='ru',8,9))))))))) `language_priority`
        FROM `".$db_name."`.`tech_regions_names`,`".$db_name."`.`tech_regions_positions`
        WHERE `tech_regions_names`.`region_id`=`tech_regions_positions`.`region_id` AND `tech_regions_names`.`country_id`=".waysql_secure($_POST['country_id'])."
            AND
                (
                (
                (".waysql_secure($_POST['ML'])."<=`tech_regions_positions`.`longitude_left` AND `tech_regions_positions`.`longitude_left`<=".waysql_secure($_POST['MR']).")
                OR
                (".waysql_secure($_POST['ML'])."<=`tech_regions_positions`.`longitude_right` AND `tech_regions_positions`.`longitude_right`<=".waysql_secure($_POST['MR']).")
                )
                AND
                (
                (".waysql_secure($_POST['MT']).">=`tech_regions_positions`.`latitude_top` AND `tech_regions_positions`.`latitude_top`>=".waysql_secure($_POST['MB']).")
                OR
                (".waysql_secure($_POST['MT']).">=`tech_regions_positions`.`latitude_bottom` AND `tech_regions_positions`.`latitude_bottom`>=".waysql_secure($_POST['MB']).")
                )
                )
 


Вопрос:
Если добавить выборку по country_id, это ускорит процесс? Какие индексы для такого запроса лучше тогда использовать?


Скажи миру - НЯ!

Неактивен

 

#2 11.11.2012 16:43:14

animegirl
Активист
Зарегистрирован: 28.07.2011
Сообщений: 288

Re: Ускорит или замедлит?

Вообще, как работает MySQL она ищет по всем столбцам запроса сразу все строчки, или же сначала берёт первое искомое, прогоняет его, находит соответствия, а второе уже гонит по результату первого?


Скажи миру - НЯ!

Неактивен

 

#3 12.11.2012 03:20:22

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Ускорит или замедлит?

animegirl написал:

Вопрос:
Если добавить выборку по country_id, это ускорит процесс?

О каком процессе идет речь?
Понятно, когда речь идет об изменении запроса с целью улучшения производительности (подзапрос переписать через join, разбить запрос не несколько простых и т.д.) Но вы сравниваете два разных запроса в рамках какого-то процесса.


animegirl написал:

Какие индексы для такого запроса лучше тогда использовать?

Посмотрите explain, если `tech_regions_names` главная в объединении, то достаточно на country_id, иначе на (`region_id`,country_id).
Кроме того важно сколько уникальных значений принимает country_id, если мало, то и смысла в индексе на эту колонку нет.

Неактивен

 

#4 12.11.2012 03:20:49

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Ускорит или замедлит?

animegirl написал:

Вообще, как работает MySQL она ищет по всем столбцам запроса сразу все строчки, или же сначала берёт первое искомое, прогоняет его, находит соответствия, а второе уже гонит по результату первого?

сразу

Неактивен

 

#5 12.11.2012 03:27:49

animegirl
Активист
Зарегистрирован: 28.07.2011
Сообщений: 288

Re: Ускорит или замедлит?

vasya написал:

animegirl написал:

Вопрос:
Если добавить выборку по country_id, это ускорит процесс?

О каком процессе идет речь?
Понятно, когда речь идет об изменении запроса с целью улучшения производительности (подзапрос переписать через join, разбить запрос не несколько простых и т.д.) Но вы сравниваете два разных запроса в рамках какого-то процесса.


animegirl написал:

Какие индексы для такого запроса лучше тогда использовать?

Посмотрите explain, если `tech_regions_names` главная в объединении, то достаточно на country_id, иначе на (`region_id`,country_id).
Кроме того важно сколько уникальных значений принимает country_id, если мало, то и смысла в индексе на эту колонку нет.

Почему? Это одинаковые запросы, только во втором добавлено `tech_regions_names`.`country_id`= оно не обязательно, найдут и без него, но как вы сами написали, стран будет не более 250, а регионов скажем 20000 языков возьмём будет 100, это уже 200к строк, и это регионы, дальше идут города, это уже сходу можно добавит 3 нуля в сумму строк. Вот я и подумала, что если указывать ИД верхней зоны, укорочу-ли я тем самым список который будет перебираться?


Скажи миру - НЯ!

Неактивен

 

#6 12.11.2012 03:30:22

animegirl
Активист
Зарегистрирован: 28.07.2011
Сообщений: 288

Re: Ускорит или замедлит?

country_id не всегда будет присутствовать в передачи данных, какой из вариантов лучше выбрать:
1. Забить на него в выборке так как на исход он никак не влияет
2. добавить его в том виде как сейчас, индекс на region_id и индекс на country_id
3. добавить его сделав индекс на обе колонки country_id вместе с region_id
?


Скажи миру - НЯ!

Неактивен

 

#7 12.11.2012 04:25:19

animegirl
Активист
Зарегистрирован: 28.07.2011
Сообщений: 288

Re: Ускорит или замедлит?

Я не могу понять такую вещь, если делать индексы, нужно делать сразу по всем колонкам, что заданы в запросе, или же если допустим колонки 3 и только одна индекс, оно тоже поможет?


Скажи миру - НЯ!

Неактивен

 

#8 12.11.2012 07:38:37

Shopen
Гуру
Откуда: Москва
Зарегистрирован: 22.10.2007
Сообщений: 362

Re: Ускорит или замедлит?

animegirl написал:

Я не могу понять такую вещь, если делать индексы, нужно делать сразу по всем колонкам, что заданы в запросе, или же если допустим колонки 3 и только одна индекс, оно тоже поможет?

Всё зависит от ваших данных. По всем колонкам это как правило нерентабельно
Во-первых, если не трудно - приводите запросы без вот этих конструкций '.waysql_secure($_POST['MB']).', поставьте туда конкретные данные, так и читать будет легче гораздо, и сразу будет видно какие типы данных используются.
Во-вторых, сделайте пожалуйста EXPLAIN этих двух запросов и покажите, а то мы тут вилами по воде практически

Я бы сделал в первой таблице индекс region_id+country_id, а во-второй region_id + 4 индекса (left,top,right,bottom) и проверил експлейном (не уверен что mysql последние будет использовать). Но это опять же не зная данных

Кстати это что вообще, вот эти top,bottom,left,right - координаты? координаты чего?

Неактивен

 

#9 12.11.2012 22:07:49

animegirl
Активист
Зарегистрирован: 28.07.2011
Сообщений: 288

Re: Ускорит или замедлит?

Извиняюсь, там везде цифры, я думала из таблицы будет понятно, там же тип указан вроде.
Сейчас попытаюсь эксплайн сделать.

Так там ведь и так они именно так сделаны, или вы предлагаете вообще все 5 столбцов в один индекс, разве это разумно? Ведь тоже самое, что и без индексов совсем. Хотя может быть я не верно понимают их работу. А по поводу взять в один индекс region_id и country_id, можно, но country_id, он не всегда имеется, иногда надо без него, это опционально, если передаётся, то можно использовать, весь вопрос в том, имеет ли смысл вообще использовать?

Это координаты открытой карты, края карты.


Скажи миру - НЯ!

Неактивен

 

#10 13.11.2012 00:01:10

Shopen
Гуру
Откуда: Москва
Зарегистрирован: 22.10.2007
Сообщений: 362

Re: Ускорит или замедлит?

нет, у вас один составной индекс, работать из него будет в лучшем случе только левая часть (top), я же вам написал про 4 отдельных индекса

Неактивен

 

#11 13.11.2012 00:25:42

animegirl
Активист
Зарегистрирован: 28.07.2011
Сообщений: 288

Re: Ускорит или замедлит?

Так

CREATE TABLE IF NOT EXISTS `tech_regions_positions2` (
  `region_id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
  `latitude_top` double(9,6) NOT NULL,
  `latitude_bottom` double(9,6) NOT NULL,
  `longitude_left` double(9,6) NOT NULL,
  `longitude_right` double(9,6) NOT NULL,
  PRIMARY KEY (`region_id`),
  KEY `latitude_top` (`latitude_top`),
  KEY `latitude_bottom` (`latitude_bottom`),
  KEY `longitude_left` (`longitude_left`),
  KEY `longitude_right` (`longitude_right`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=2 ;

?


Скажи миру - НЯ!

Неактивен

 

#12 13.11.2012 02:50:01

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Ускорит или замедлит?

animegirl написал:

Почему? Это одинаковые запросы, только во втором добавлено `tech_regions_names`.`country_id`= оно не обязательно, найдут и без него

Т.е. независимо от того если ли условие по country_id результат будет одинаков?
Тогда нужно смотреть eplain, если tech_regions_names главная в объединении, то ускорит выборку, в противном случае замедлит (незначительно).

Что касается работы составных индексов, то рекомендую посмотреть FAQ №5

Неактивен

 

#13 15.11.2012 15:54:16

animegirl
Активист
Зарегистрирован: 28.07.2011
Сообщений: 288

Re: Ускорит или замедлит?

SQL query: EXPLAIN SELECT `tech_regions_positions`.`region_id`,`tech_regions_names`.`region_language`,IF(`region_language`='ur',0,IF(`region_language`='en',1,IF(`region_language`='cn',2,IF(`region_language`='es',3,IF(`region_language`='jp',4,IF(`region_language`='pt',5,IF(`region_language`='de',6,IF(`region_language`='fr',7,IF(`region_language`='ru',8,9))))))))) `language_priority` FROM `way`.`tech_regions_names`,`way`.`tech_regions_positions` WHERE `tech_regions_names`.`region_id`=`tech_regions_positions`.`region_id` AND ( ( (25<=`tech_regions_positions`.`longitude_left` AND `tech_regions_positions`.`longitude_left`<=25) OR (25<=`tech_regions_positions`.`longitude_right` AND `tech_regions_positions`.`longitude_right`<=25) ) AND ( (25>=`tech_regions_positions`.`latitude_top` AND `tech_regions_positions`.`latitude_top`>=25) OR (25>=`tech_regions_positions`.`latitude_bottom` AND `tech_regions_positions`.`latitude_bottom`>=25) ) );
Rows: 2
id     select_type     table     type     possible_keys     key     key_len     ref     rows     Extra
1     SIMPLE     tech_regions_positions     index     PRIMARY,region_GCS     region_GCS     32     NULL     1     Using where; Using index
1     SIMPLE     tech_regions_names     ref     PRIMARY,region_id     PRIMARY     3     way.tech_regions_positions.region_id     1     Using index
 



SQL query: EXPLAIN SELECT `tech_regions_positions`.`region_id`,`tech_regions_names`.`region_language`,IF(`region_language`='ur',0,IF(`region_language`='en',1,IF(`region_language`='cn',2,IF(`region_language`='es',3,IF(`region_language`='jp',4,IF(`region_language`='pt',5,IF(`region_language`='de',6,IF(`region_language`='fr',7,IF(`region_language`='ru',8,9))))))))) `language_priority` FROM `way`.`tech_regions_names`,`way`.`tech_regions_positions` WHERE `tech_regions_names`.`region_id`=`tech_regions_positions`.`region_id` AND `tech_regions_names`.`country_id`=1 AND ( ( (25<=`tech_regions_positions`.`longitude_left` AND `tech_regions_positions`.`longitude_left`<=25) OR (25<=`tech_regions_positions`.`longitude_right` AND `tech_regions_positions`.`longitude_right`<=25) ) AND ( (25>=`tech_regions_positions`.`latitude_top` AND `tech_regions_positions`.`latitude_top`>=25) OR (25>=`tech_regions_positions`.`latitude_bottom` AND `tech_regions_positions`.`latitude_bottom`>=25) ) );
Rows: 2
id     select_type     table     type     possible_keys     key     key_len     ref     rows     Extra
1     SIMPLE     tech_regions_positions     index     PRIMARY,region_GCS     region_GCS     32     NULL     1     Using where; Using index
1     SIMPLE     tech_regions_names     ref     PRIMARY,region_id,country_id     PRIMARY     3     way.tech_regions_positions.region_id     1     Using where
 


Скажи миру - НЯ!

Неактивен

 

#14 15.11.2012 15:56:25

animegirl
Активист
Зарегистрирован: 28.07.2011
Сообщений: 288

Re: Ускорит или замедлит?

Я ещё что подумала, есть смысл заменить

(25<=`tech_regions_positions`.`longitude_left` AND `tech_regions_positions`.`longitude_left`<=25)
на
(`tech_regions_positions`.`longitude_left` BETWEEN 25 AND 25)
?


Скажи миру - НЯ!

Неактивен

 

#15 15.11.2012 16:42:47

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Ускорит или замедлит?

animegirl написал:

Я ещё что подумала, есть смысл заменить

(25<=`tech_regions_positions`.`longitude_left` AND `tech_regions_positions`.`longitude_left`<=25)
на
(`tech_regions_positions`.`longitude_left` BETWEEN 25 AND 25)
?

Нет, это синонимы.

Explain показывает, что объединение идет с таблицы tech_regions_positions и дополнительное условие на `country_id` ухудшает план, приводя к лишней проверке. (Using where во втором плане)

Неактивен

 

#16 15.11.2012 16:50:35

animegirl
Активист
Зарегистрирован: 28.07.2011
Сообщений: 288

Re: Ускорит или замедлит?

Понятно, значит убрать. А по поводу индексов, я ведь в итоге правильно их объединила? Я прочила тему по ссылке из фага, если я правильно поняла, то у меня уже всё верно, или?


Скажи миру - НЯ!

Неактивен

 

#17 15.11.2012 17:31:50

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Ускорит или замедлит?

У вас действительно используется весь составной индекс, но лишь по причине того, что вы рассматриваете частный случай, когда верхняя и нижняя границы диапазона равны, т.е. ваше условие эквивалентно
( `longitude_left`=25 OR `longitude_right`=25 ) AND ( `latitude_top`=25 OR `latitude_bottom`=25 )

В противном случае картина будет совсем другой. Кстати, и условие на country_id тоже нужно проверять на общем случае.

Неактивен

 

#18 15.11.2012 17:42:36

animegirl
Активист
Зарегистрирован: 28.07.2011
Сообщений: 288

Re: Ускорит или замедлит?

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


Скажи миру - НЯ!

Неактивен

 

#19 15.11.2012 17:50:41

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Ускорит или замедлит?

«Преждевременная оптимизация - корень всех зол»

http://webew.ru/articles/275.webew

Неактивен

 

#20 15.11.2012 18:32:48

Shopen
Гуру
Откуда: Москва
Зарегистрирован: 22.10.2007
Сообщений: 362

Re: Ускорит или замедлит?

vasya написал:

Explain показывает, что объединение идет с таблицы tech_regions_positions и дополнительное условие на `country_id` ухудшает план, приводя к лишней проверке. (Using where во втором плане)

Как это к лишней? )
Это же все равно что искать в базе Ивановых, но если среди них искать еще и Андреев - то новое условие ухудшит план )))


animegirl написал:

Значит убрать

Условие либо нужно либо нет, если результат не зависит от country_id - то зачем вообще это условие в запросе? Если country_id влияет на запрос - как вы его уберете, если оно необходимо для уточнения результата?

Пусть region_id - это фамилия, а country_id имя. Вам всегда нужно из базы выбирать только по фамилиям? Или по фамилии и имени тоже бывает нужно? Если первое, то индекс нужен только по фамилии, если второе - то имеет смысл сделать составной индекс фамилия+имя.

Вот вы explain привели - вижу там что есть доступный индекс country_id - это индекс по полю country_id или составной по region_id+country_id (как я вам писал выше)? Если по только country_id - в нем вообще никакого смысле нет при ваших запросах. А составной может привести к тому, что у запроса может план выполнения поменяться на противоположный, т.к. грамотно составные  составные индексы, как правило очень селективны и оптимизатор может поменять мнение о том, с какой таблицы начинать.

Неактивен

 

#21 15.11.2012 18:35:56

animegirl
Активист
Зарегистрирован: 28.07.2011
Сообщений: 288

Re: Ускорит или замедлит?

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


Скажи миру - НЯ!

Неактивен

 

#22 15.11.2012 18:38:41

Shopen
Гуру
Откуда: Москва
Зарегистрирован: 22.10.2007
Сообщений: 362

Re: Ускорит или замедлит?

а что в этом поле? region_id = country_id, они равны?

Неактивен

 

#23 15.11.2012 18:41:21

Shopen
Гуру
Откуда: Москва
Зарегистрирован: 22.10.2007
Сообщений: 362

Re: Ускорит или замедлит?

Кстати

CREATE TABLE IF NOT EXISTS `tech_regions_names` (
....
  PRIMARY KEY (`region_id`,`region_language`),
  KEY `region_id` (`region_id`),
...
) ...


индекс region_id - лишний, т.к. является префиксом PRIMARY

Неактивен

 

#24 15.11.2012 18:41:55

animegirl
Активист
Зарегистрирован: 28.07.2011
Сообщений: 288

Re: Ускорит или замедлит?

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


Скажи миру - НЯ!

Неактивен

 

#25 15.11.2012 18:42:35

animegirl
Активист
Зарегистрирован: 28.07.2011
Сообщений: 288

Re: Ускорит или замедлит?

Shopen написал:

Кстати

CREATE TABLE IF NOT EXISTS `tech_regions_names` (
....
  PRIMARY KEY (`region_id`,`region_language`),
  KEY `region_id` (`region_id`),
...
) ...


индекс region_id - лишний, т.к. является префиксом PRIMARY

Поняла, спасибо. Буду знать


Скажи миру - НЯ!

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson