За последние 24 часа нас посетили 16652 программиста и 1651 робот. Сейчас ищут 1570 программистов ...

join и between

Тема в разделе "MySQL", создана пользователем Alex870, 13 ноя 2016.

  1. Alex870

    Alex870 Новичок

    С нами с:
    8 дек 2013
    Сообщения:
    121
    Симпатии:
    2
    Здравствуйте, форумчане!
    Нужен совет, поделитесь опытом.
    Есть две таблицы с географическими координатами точек.
    Допустим так:
    table1 (Long decimal(12,8),Lat decimal(12,8),present int)
    и table2(Long decimal(12,8),Lat decimal(12,8))
    В обеих таблицах созданы составные индексы по полям Long и Lat
    Задача написать запрос, который апдейтит поле present в table1 если такие координаты есть в table2.
    Но проблема заключается в том, что требуется не точное совпадение, а +/- delta. Delta = 0.002
    Пишу так:
    Код (Text):
    1. update table1 t1 join table2 t2 on t1.Long between t2.aLong-0.002 and t2.aLong+0.002 and t1.Lat between t2.aLat-0.002 and t2.aLat+0.002 set t1.present = 1
    Но эта вещь оказывается убийственной для сервера. На мощном сервере она всё-таки завершилась, но работала более 2 часов, на моем домашнем (слабеньком) 6 часов и нет результатов.
    В таблице table1 36000 записей, в table2 188000 записей.
     
  2. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Дай дамп чтоб потестить
     
  3. Chushkin

    Chushkin Активный пользователь

    С нами с:
    17 дек 2010
    Сообщения:
    1.062
    Симпатии:
    91
    Адрес:
    Мещёра, Центр, Болото N3
    Присоединяюсь. Запрос должен выполняться меньше секунды.
    --- Добавлено ---
    Пожалуй я погорячился.
    Поправка: Запрос должен выполняться несколько секунд.
     
  4. Alex870

    Alex870 Новичок

    С нами с:
    8 дек 2013
    Сообщения:
    121
    Симпатии:
    2
  5. Chushkin

    Chushkin Активный пользователь

    С нами с:
    17 дек 2010
    Сообщения:
    1.062
    Симпатии:
    91
    Адрес:
    Мещёра, Центр, Болото N3
    Разместите в другом месте, - гугл требует авторизации.
     
  6. Alex870

    Alex870 Новичок

    С нами с:
    8 дек 2013
    Сообщения:
    121
    Симпатии:
    2
  7. Chushkin

    Chushkin Активный пользователь

    С нами с:
    17 дек 2010
    Сообщения:
    1.062
    Симпатии:
    91
    Адрес:
    Мещёра, Центр, Болото N3
    Нормально
     
  8. Alex870

    Alex870 Новичок

    С нами с:
    8 дек 2013
    Сообщения:
    121
    Симпатии:
    2
    Попробовал составной индекс разделить на 2. Всё равно он не используется, если верить explain.
     
  9. Chushkin

    Chushkin Активный пользователь

    С нами с:
    17 дек 2010
    Сообщения:
    1.062
    Симпатии:
    91
    Адрес:
    Мещёра, Центр, Болото N3
    Естественно долго будет, т.к. идёт пересечение таблиц (т.е. будет отработано около 6 млрд. чтений из таблиц, это долго)
    Попробуй заменить выражение на эквивалент, чтобы использовался индекс:
    PHP:
    1. update table1 t1
    2. -- join table2 t2 on (t1.Long between t2.aLong-0.002 and t2.aLong+0.002) and (t1.Lat between t2.aLat-0.002 and t2.aLat+0.002)
    3. join table2 t2 on (t1.Long+0.002 >= t2.aLong and t1.Long-0.002 <= t2.aLong) and (t1.Lat+0.002 >= t2.aLat and t1.Lat-0.002 <= t2.aLat)
    4. set t1.present = 1
    У меня отрабатывает ~1.1 секунды (mySQL-5.6, Innodb, Win-7).
    Только надо проверить результат. Теоретически всё правильно, но вдруг я ошибаюсь...
     
    Alex870 нравится это.
  10. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    @Chushkin а оригинальный запрос сколько у тебя отрабатывает?
     
  11. Chushkin

    Chushkin Активный пользователь

    С нами с:
    17 дек 2010
    Сообщения:
    1.062
    Симпатии:
    91
    Адрес:
    Мещёра, Центр, Болото N3
    Много, - через 5 минут остановил выполнение.
    Судя по скорости работы движка будет отрабатывать где-то от часа до двух.
     
  12. Alex870

    Alex870 Новичок

    С нами с:
    8 дек 2013
    Сообщения:
    121
    Симпатии:
    2
    @Chushkin Спасибо!
    Если это работает с индексами - я неимоверно благодарен :). Правда explain мне показал, что этот запрос тоже индексы не использует, но это ещё проверить надо. Сейчас перезагружу таблицы, хочу удалить от туда южное полушарие и западное. Короче четверть земли оставлю, остальное пока не интересно.
     
  13. Chushkin

    Chushkin Активный пользователь

    С нами с:
    17 дек 2010
    Сообщения:
    1.062
    Симпатии:
    91
    Адрес:
    Мещёра, Центр, Болото N3
    Explain показывает "Range checked for each record (index map: 0x2)". Т.е. индекс используется, если верить доке. Да и результат говорит за это.
     
    Alex870 нравится это.
  14. Alex870

    Alex870 Новичок

    С нами с:
    8 дек 2013
    Сообщения:
    121
    Симпатии:
    2
    Спасибо огромное, у меня дома на слабой железяке (ARM Linux 512 Mb RAM) всё отработало за несколько секунд!
    Добавлю, всё отработало корректно.