Используем второй способ. Именно так реализована MVCC в InnoDB (MySQL) — оттуда о нём и узнали. Только там вместо дат используются внутренние номера транзакций.
У нас же реализация полностью на ПХП (MySQL еще недорос для перекладывания на неге какой-либо логики) как extension к Yii.
Было интересно узнать про другие способы, спасибо.
Вы правы, предполагается, что индекс по price, height, id есть. Но даже если Вы перепишете запрос через UNION ALL, то он все-равно понадобится, если Вы захотите отсортировать записи по height, price и при этом ни height, ни price не являются уникальным полем.
Что касается размера индексов и времени вставки… Тут все сильно зависит от проекта. Обычно все же вставки происходят намного реже. Вы вставляете статью 1 раз, а прочитать ее могут, скажем 1000 человек. Даже если селект будет делаться не все 1000 раз благодаря кэшу, то выигрыш все-равно очевиден. А по поводу того, что с каждым разом вставки будут все медленнее — очень спорный вопрос…
Пожалуй, самый распространенный способ предложен в этом комментарии habrahabr.ru/blogs/mysql/44608/#comment_1121189 и habrahabr.ru/blogs/mysql/44608/#comment_1120939. То есть, первым запросом вы выбираете ТОЛЬКО данные, необходимые для пэйджинга (id и height, например) сразу для 10-ти страниц + 1 (101 запись, например) и кладете все это в кэш. Мотаете так же как обычно, только для каждой циферки в меню подставляете нужные параметры для id и height.
Вы не совсем правильно поняли…
С одной стороны, надо было бы получить количество записей, и взять остаток от деления на количество записей на странице. То есть, если у нас получилось 1234567 записей, а выводим мы по 10, то на последней странице должно быть 7 записей начиная с 1234561-й.
Так как COUNT делать медленно, то мы можем просто показать последние 10 записей — никто даже не заметит подвоха:) Делается это через SELECT… ORDER BY id DESC LIMIT 10. В этом случае MySQL просто прочитает первые 10 записей с конца нашей таблицы, что не составит особого труда.
mysql> select * from items where id in (select id from items where height>100 LIMIT 90000,10);
ERROR 1235 (42000): This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
Вы знаете, все-же этот способ не очень хорош тем, что скорость его выполнения зависит от того, на которой странице Вы находитесь. Если Вы сделаете WHERE id>1000000 ORDER BY id LIMIT 10, то этот запрос по скорости не будет зависеть от того, какое число будет в id>XXX.
Если у Вас нет проблем с производительностью — то этого вполне достаточно. Единственный момент, лучше все-таки делать два запроса — один, который делать COUNT (и его резальтат кэшировать) + запрос, который собственно выбирает данные (который использует LIMIT… OFFSET). Если вы будете использовать SQL_CALC_FOUND_ROWS в КАЖДОМ запросе, то это будет практически равносильно выполению SELECT без LIMIT.
эм… совсем без уникального поля не обойтись… А пример с сортировкой по неуникальному полю есть в статье, но при этом уникальное поле тоже используется:)
Именно. Я упомянул в самом начале, что используя предложенную технологию можно и не отказываться от стандартного меню навигации — все зависит от Вашей фантазии и умения работы с кэшем:)
Вы знаете, специально не стал писать здесь про index merge, так как, если честно мне редко удается его добиться… Пробовал даже (x AND y) OR z = (x OR z) AND (y OR z), но говорят, что mysql пока не очень умно с ним работает…
Что касается UNION — проверил конкретно на своих примерах — работает медленнее, поэтому и не стал про это писать:)
Судя по статье и комментариям, я так понимаю, что Вы используете именно md5 для ключей. Ничего п ротив не имею, лишь хочу рассказать, почему использую вот этот способ: friends_192_public_sorted_online.
1) Ключ всегда будет уникальным, так как используются id из таблиц
2) Формирование ключа занимает меньше времени
3) Правила формирования всех ключей храню в одном месте, поэтому в любой момент к ним можно обратиться и узнать, из чего состоит каждый ключ.
4) Есть самописный консольный клиент, который позволяет читать/писать/удалять из мемкэша по ключу. Очень удобно бывает. С md5-ключами работать было бы сложнее.
5) Ключи не обязательно делать такими длинными. Вполне достаточно fr_192_pub_asc_1.
У нас же реализация полностью на ПХП (MySQL еще недорос для перекладывания на неге какой-либо логики) как extension к Yii.
Было интересно узнать про другие способы, спасибо.
Что касается размера индексов и времени вставки… Тут все сильно зависит от проекта. Обычно все же вставки происходят намного реже. Вы вставляете статью 1 раз, а прочитать ее могут, скажем 1000 человек. Даже если селект будет делаться не все 1000 раз благодаря кэшу, то выигрыш все-равно очевиден. А по поводу того, что с каждым разом вставки будут все медленнее — очень спорный вопрос…
ПС. ориентировочно — в понедельник
С одной стороны, надо было бы получить количество записей, и взять остаток от деления на количество записей на странице. То есть, если у нас получилось 1234567 записей, а выводим мы по 10, то на последней странице должно быть 7 записей начиная с 1234561-й.
Так как COUNT делать медленно, то мы можем просто показать последние 10 записей — никто даже не заметит подвоха:) Делается это через SELECT… ORDER BY id DESC LIMIT 10. В этом случае MySQL просто прочитает первые 10 записей с конца нашей таблицы, что не составит особого труда.
ERROR 1235 (42000): This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
Что касается UNION — проверил конкретно на своих примерах — работает медленнее, поэтому и не стал про это писать:)
1) Ключ всегда будет уникальным, так как используются id из таблиц
2) Формирование ключа занимает меньше времени
3) Правила формирования всех ключей храню в одном месте, поэтому в любой момент к ним можно обратиться и узнать, из чего состоит каждый ключ.
4) Есть самописный консольный клиент, который позволяет читать/писать/удалять из мемкэша по ключу. Очень удобно бывает. С md5-ключами работать было бы сложнее.
5) Ключи не обязательно делать такими длинными. Вполне достаточно fr_192_pub_asc_1.