ФорумРазработкаБазы данных → нешутоШный запрос

нешутоШный запрос

  • sweet15w

    Сообщения: 139 Репутация: N Группа: Кто попало

    Spritz 21 ноября 2011 г. 20:22

    есть две таблицы (mysql)…

    viewer_checked ( 2,714 записей )

    id | int auto_increment
    surname | text
    name | text
    patronymic | text
    organization | text
    post | text
    phone | text
    email | text
    activate | int
    who | int
    client | int
    date_active | int
    branch | int



    subscription (13,326 записей)

    id | int auto_increment
    type | int
    email | text
    date | int
    activate | int
    date_active | int


    написал запрос:
    (
    select distinct
    email,
    date_active
    from
    subscription
    where
    activate = '1'
    order by
    date_active,
    email
    )
    union
    (
    select distinct
    email,
    date_active
    from
    viewer_checked
    where
    email not in (
    select distinct
    email
    from
    subscription
    where
    activate = '1'
    order by
    date_active,
    email
    ) and
    activate = '1'
    order by
    date_active,
    email
    )
    order by date_active, email



    дк вот… на локальном компьютере phpmyadmin не может справиться с запросом… слабенький… а на серве выполняется, но за 30 секунд…
    правда данная муть проходит раз в ночь… кроном… но есть ли какая нибудь возможность как то ускорить данный скрипт?? (((
  • artoodetoo

    Сообщения: 5139 Репутация: N Группа: в ухо

    Spritz 21 ноября 2011 г. 21:36, спустя 1 час 13 минут 41 секунду

    ты не написал назначение таблиц и что хочешь получить на выходе.
    ιιlllιlllι унц-унц
  • sweet15w

    Сообщения: 139 Репутация: N Группа: Кто попало

    Spritz 21 ноября 2011 г. 22:30, спустя 54 минуты 6 секунд

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

    выбираю все уникальные записи с первой таблицы и объединяю с уникальными записями второй с исключением повторов первой таблицы…

    эта вся муть для расслыки… поэтому еще учитывается поле date_active - дата активности данного email.. когда он проверился… то происходит изменение даты активности… т.к. на хостинге разрешена отправка только 1000 писем в сутки… после 900 отправки писем происходит прерывание скрипта, в следующий день продолжается с того места, на котором был прерван скрипт…
  • Faster

    Сообщения: 1159 Репутация: N Группа: Кто попало

    Spritz 21 ноября 2011 г. 23:13, спустя 43 минуты 6 секунд

    очень хуевая тема юзать SELECT во WHERE
    Спустя 16 сек.
    больше так не делай
  • artoodetoo

    Сообщения: 5139 Репутация: N Группа: в ухо

    Spritz 21 ноября 2011 г. 23:33, спустя 19 минут 54 секунды

    что за activate = '1' не рассказал. наверное флаг что почта высылалась. если так, то достаточно условия на дату.
    не делай для строковых полей тип text. это blob поле и работает медленно по сравнению с varchar

    главные тормоза конечно от not in select, хотя каждый distinct добавляет свои 5коп и бессмысленный order by в промежуточных запросах тоже


    Спустя 61 сек.
    в целом говно то еще.
    ιιlllιlllι унц-унц
  • Nyaah

    Сообщения: 574 Репутация: N Группа: Джедаи

    Spritz 22 ноября 2011 г. 0:01, спустя 27 минут 38 секунд

    бд в третью нормальную форму приведи, и запросы упростятся и сущности дублироваться перестанут (DISTINCT не нужен будет) и таблицы места меньше станут занимать на диске/в памяти
    Work, buy, consume, die
  • sweet15w

    Сообщения: 139 Репутация: N Группа: Кто попало

    Spritz 22 ноября 2011 г. 1:45, спустя 1 час 44 минуты 11 секунд

    раньше запрос был выполнен за 35.4826 сек.

    после того, как я убрал три лишнии сортировки запрос был выполнен за 40.7410 сек. :(

    (
    select distinct
    email,
    date_active
    from
    subscription
    where
    activate = '1'
    )
    union
    (
    select distinct
    email,
    date_active
    from
    viewer_checked
    where
    email not in (
    select distinct
    email
    from
    subscription
    where
    activate = '1'
    ) and
    activate = '1'
    )
    order by
    date_active,
    email



    очень хуевая тема юзать SELECT во WHERE
    я это понимаю… но как быть, у заказчика все время какие-то новые непонятные идеи… после которых и приходится идти на всякие извраты…

    что за activate = '1' не рассказал. наверное флаг что почта высылалась. если так, то достаточно условия на дату…
    activate = '1' это активированные пользователи… так что не достаточно условия на дату…


    не делай для строковых полей тип text. это blob поле и работает медленно по сравнению с varchar

    после перевода text в varchar второй запрос выполнился за 33.1043 сек.,

    а первый за 38.3414 сек.




    бд в третью нормальную форму приведи, и запросы упростятся и сущности дублироваться перестанут (DISTINCT не нужен будет) и таблицы места меньше станут занимать на диске/в памяти
    видимо так и сделаю…
  • phpdude

    Сообщения: 26624 Репутация: N Группа: в ухо

    Spritz 22 ноября 2011 г. 2:04, спустя 18 минут 50 секунд

    Чуток подчистил запрос. Глянь такой возвращает теже результаты или другие получились? :)

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

    (
    select distinct email, date_active
    from
    subscription
    where activate = '1'
    )
    union
    (
    select distinct v.email, v.date_active
    from viewer_checked v
    left join subscription s USING(email)
    where s.id = null and e.activate = 1 and s.activate = 1
    )
    order by date_active, email


    Чтобы работало быстро - надо с индексами поиграться. Данных тут немного, так что он в принцип за 0.5 максимум должен выполняться при должных условиях
    Спустя 178 сек.
    зы: Для начала поле email в обоих таблицах должно быть индексируемым.

    Предположительные индексы -

    для Subscription
    1. activate, email, date_active
    2. email, id, activate, date_active

    для viewer_checked
    1. activate, email, date_active

    Хотя по факту возможно хватит и первого индекса на оба случая, но не думаю)

    Но без данных живых это только догадки :)
    Сапожник без сапог
  • Ivan

    Сообщения: 1316 Репутация: N Группа: Адекваты

    Spritz 22 ноября 2011 г. 3:00, спустя 55 минут 52 секунды

    EXPLAIN тебе в помощь
  • phpdude

    Сообщения: 26624 Репутация: N Группа: в ухо

    Spritz 22 ноября 2011 г. 3:03, спустя 3 минуты 32 секунды


    EXPLAIN тебе в помощь
    Да, КЭП! :-)

    он всем поможет)
    Сапожник без сапог
  • AlexB

    Сообщения: 4290 Репутация: N Группа: в ухо

    Spritz 22 ноября 2011 г. 4:18, спустя 1 час 14 минут 30 секунд


    EXPLAIN тебе в помощь
    Точно. Я уже устал возмущаться, что люди вместо того, чтобы просто взять и посмотреть план, предпочитают гадать на кофейной куще, да еще привлечь к этому гаданию целый форум. )))))
  • master

    Сообщения: 3236 Репутация: N Группа: Джедаи

    Spritz 22 ноября 2011 г. 5:31, спустя 1 час 12 минут 53 секунды

    люди вместо того, чтобы просто взять и посмотреть план

    может ещё мануал почитать, лол
    не всё полезно, что в swap полезло
  • artoodetoo

    Сообщения: 5139 Репутация: N Группа: в ухо

    Spritz 22 ноября 2011 г. 8:25, спустя 2 часа 54 минуты 57 секунд

    всем: не поймет он результатов explain

    топикстартеру: у тебя несколько видов подписок для незарегистрированных, а для пользователей получается нет разбивки. что-то тут не так. логика хромает.
    1) полноценные пользователи должны аналогично попадать в таблицу "подписка" и получишь один простой запрос
    2) чтобы выборка уникальных email была быстрой, сделай его символьным и индексируй его.
    будет работать доли секунды

    30 или 40 сек: я думаю реально у тебя разброс +- 50% по времени, так что такие наблюдения ниочем. наведи порядок кардинально

    ιιlllιlllι унц-унц
  • phpdude

    Сообщения: 26624 Репутация: N Группа: в ухо

    Spritz 22 ноября 2011 г. 8:36, спустя 10 минут 37 секунд

    2) чтобы выборка уникальных email была быстрой, сделай его символьным и индексируй его.

    char(50) будет более чем достаточно :-)
    Сапожник без сапог
  • Faster

    Сообщения: 1159 Репутация: N Группа: Кто попало

    Spritz 22 ноября 2011 г. 10:36, спустя 1 час 59 минут 43 секунды

    varchar медленнее?

Пожалуйста, авторизуйтесь, чтобы написать комментарий!