WedX - журнал о программировании и компьютерных науках

Рекомендации для лучшей производительности запросов (MySQL)

Я ищу лучший запрос MySQL для этой ситуации:

Я перечисляю 10 последних сообщений члена.

table for posts:
post_id | uid | title | content | date

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

Так что можно выбрать последние сообщения с идентификатором пользователя X и идентификатором пользователя Y. Но я хотел бы разрешить участникам отключать отображение некоторых сообщений (тех, которые он не хочет отображать).

Моя проблема: как я могу сделать это максимально простым для MySQL?... Я подумал о второй таблице, где я помещаю идентификаторы сообщений, которые не нужны пользователю:

table postdenied
uid | post_id

Затем сделайте выбор, например:

select * from posts as p where not exists (select 1 from postdenied as d where d.post_id = p.post_id and d.uid = p.uid) order by date DESC limit 10

Я прав? Или есть что-то лучше?

Спасибо

05.08.2013

  • почему вы получаете все сообщения, если вам нужны только последние 10? 05.08.2013
  • Да, извините, я забыл порядок по дате DESC limit 10 05.08.2013
  • Почему вы не используете JOIN? 05.08.2013
  • В столбце posts.uid хранится идентификатор постера? 05.08.2013
  • Структура, которую я дал, была идеей, возможно, есть гораздо более эффективная структура/таблицы? 05.08.2013
  • Учитывая ваши комментарии, на самом деле неясно, о чем вы здесь просите. 06.08.2013
  • Я просто спрашиваю, как лучше всего реализовать эту функцию: пользователь может удалить сообщение из своего списка. Мне нужны табличные структуры и запросы для лучшей производительности. 06.08.2013

Ответы:


1

Если я правильно понимаю, в столбце posts.uid хранится ID постера. И postdenied.uid хранит идентификатор пользователя, который не хочет видеть определенный пост.

Если приведенные выше предположения верны, то ваш запрос в порядке, за исключением того, что вы не должны объединяться в столбцах uid, а только в столбцах post_id. И у вас должен быть параметр или константа userID (обозначенный как @X в приведенном ниже коде) пользователя, которому вы хотите показать все сообщения, кроме тех, которые он «отклонил»:

select p.* 
from posts as p 
where not exists 
      (select 1 
       from postdenied as d 
       where d.post_id = p.post_id 
         and d.uid = @X             -- @X is the userID of the specific user
      )                                 
order by date DESC 
limit 10 ;
05.08.2013
  • Нет, я тоже должен присоединиться к uid, потому что один пост может быть отклонен несколькими участниками в их блоге... И структура, которую я дал, была идеей, возможно, есть гораздо более эффективная структура/таблицы? 05.08.2013
  • @Recif: Можете ли вы описать, что вы хотите, чтобы запрос возвращал? Все комбинации постов-пользователей? Все сообщения (или последние 10), которые хотел бы видеть конкретный пользователь (мой ответ)? Посты, которые нравятся всем пользователям? Что-то другое? Либо опишите его, либо предоставьте нам образцы данных и образец требуемого набора результатов. 06.08.2013
  • Я бы хотел, чтобы пользователи могли удалять сообщения других, которые он не хочет видеть в своем блоге. Так что просто удалите из списка. Есть много пользователей/блогов. 06.08.2013

  • 2

    Другой подход к реализации этого — предложение LEFT JOIN.

    SELECT * FROM posts AS p 
      LEFT JOIN postdenied as d ON d.post_id = p.post_id and d.uid = p.uid
    WHERE d.uid IS NULL
    ORDER BY date DESC 
    LIMIT 10
    

    Мне неясно, будет ли это более подходящим для оптимизатора запросов. Если у вас большой объем данных, возможно, стоит протестировать оба запроса и посмотреть, является ли один из них более производительным, чем другой.

    См. https://sqlfiddle.com/#!2/be7e3/1.

    Благодарю ypercube и Lamak за их отзывы о моем первоначальном ответе

    05.08.2013
  • Что странного в NOT EXISTS? 05.08.2013
  • И запрос (как OP, так и ваш) не объединяется. Это антисоединения (часто называемые антиполусоединениями)< /а>. 05.08.2013
  • Что странно, так это то, что OP пытается объединить таблицы (и да... они являются соединениями таблиц... термин "антисоединение" является частью реляционной алгебры, а не спецификацией SQL), без использования пункт JOIN. Это ненужная запутанность, добавление ненужного SELECT и, вполне вероятно, сбивает с толку оптимизатор запросов. 05.08.2013
  • Не уверен, что вы имеете в виду. Да, антисоединение — это термин реляционной алгебры. Да, JOIN — это ключевое слово SQL. Так и EXISTS. Я не могу понять, почему вы говорите, что коррелированный подзапрос NOT EXISTS более странен, чем проверка LEFT JOIN + IS NULL. Для меня второе кажется более неестественным, но это личное мнение. Обе записи относятся к наиболее распространенным способам написания антисоединения в SQL. И оптимизатор совершенно не путается. Обычно он производит такие же или похожие планы. 06.08.2013
  • Считаете ли вы, что использование EXISTS может запутать оптимизатор запросов?, и вы даже сказали вполне возможно, есть ли какие-либо данные, подтверждающие это? 06.08.2013
  • хм... я не знаю, как поступить. Вы оба правы. Я прогнал это через EXPLAIN, и похоже, что оптимизатор на самом деле добавляет «Не существует». Итак, мой ответ является следствием моего незнания других способов реализации антисоединения. Я мог бы удалить его ... или я мог бы изменить его на «анти-ответ» в духе «Не верьте, что это лучший метод». 06.08.2013
  • Я также хотел выразить свою признательность за ваши комментарии ... Я бы предпочел, чтобы меня проголосовали против и узнали что-то о грубой ошибке в невежестве. 06.08.2013
  • @Dancrumb вообще не проблема. Возможно, вы даже правы относительно производительности LEFT JOIN ... IS NULL по сравнению с NOT EXISTS в MySQL (explainextended.com/2009/09/18/). Мой комментарий был о том, что EXISTS запутал оптимизатор. 06.08.2013
  • @Dancrumb Вы можете отредактировать, что это еще один способ написать запрос. И это может быть более эффективным в некоторых (или многих) случаях, поэтому не удаляйте его. Это действительно зависит от очень многих вещей, и с MySQL никогда не помешает попробовать множество разных способов выполнения запросов. 06.08.2013
  • Новые материалы

    Как создать диаграмму градиентной кисти с помощью D3.js
    Резюме: Из этого туториала Вы узнаете, как добавить градиентную кисть к диаграмме с областями в D3.js. Мы добавим градиент к значениям SVG и применим градиент в качестве заливки к диаграмме с..

    Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что это выглядит сложно…
    Просто начните и учитесь самостоятельно Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что он кажется мне сложным, и я бросил его. Это в основном инструмент..

    Лицензии с открытым исходным кодом: руководство для разработчиков и создателей
    В динамичном мире разработки программного обеспечения открытый исходный код стал мощной парадигмой, способствующей сотрудничеству, инновациям и прогрессу, движимому сообществом. В основе..

    Объяснение документов 02: BERT
    BERT представил двухступенчатую структуру обучения: предварительное обучение и тонкая настройка. Во время предварительного обучения модель обучается на неразмеченных данных с помощью..

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..


    Для любых предложений по сайту: [email protected]