MySQL смещает странность

0

У меня проблема с запросом MySQL с предложением OFFSET и LIMIT.

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

Я что-то делаю неправильно, или это известная "особенность" или что-то, что я где-то неправильно понял?

Если я выберу 1 столбец, смещение работает нормально. Если я добавлю второй столбец, он, как представляется, внутренне сбросит смещение на 0.

Вот мои два, казалось бы, похожих вопроса. Обратите внимание на результат в столбце id:

Два запроса повторяются: (не важно, добавляете ли вы лишние или несколько дополнительных столбцов в запрос):

mysql> SELECT t0.id, t0.max_retries FROM dtc_queue_job t0 WHERE t0.status = 'running' LIMIT 12 OFFSET 100;
+-----+-------------+
| id  | max_retries |
+-----+-------------+
| 123 |        NULL |
| 124 |        NULL |
| 125 |        NULL |
| 126 |        NULL |
| 127 |        NULL |
| 128 |        NULL |
| 129 |        NULL |
| 130 |        NULL |
| 131 |        NULL |
| 132 |        NULL |
| 133 |        NULL |
| 134 |        NULL |
+-----+-------------+
12 rows in set (0.00 sec)

mysql> SELECT t0.id FROM dtc_queue_job t0 WHERE t0.status = 'running' LIMIT 12 OFFSET 100;
+-----+
| id  |
+-----+
| 108 |
| 109 |
| 110 |
| 111 |
| 112 |
| 113 |
| 114 |
| 115 |
| 116 |
| 117 |
| 118 |
| 119 |
+-----+
12 rows in set (0.00 sec)

Фон:

1) Таблица имеет 112 записей.

2) Создать таблицу:

  CREATE TABLE 'dtc_queue_job' (
  'id' bigint(20) NOT NULL AUTO_INCREMENT,
  'worker_name' varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  'class_name' varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  'method' varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  'status' varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  'args' longtext COLLATE utf8_unicode_ci NOT NULL,
  'priority' int(11) DEFAULT NULL,
  'crc_hash' varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  'when_us' decimal(18,0) DEFAULT NULL,
  'expires_at' datetime DEFAULT NULL,
  'started_at' datetime DEFAULT NULL,
  'finished_at' datetime DEFAULT NULL,
  'elapsed' double DEFAULT NULL,
  'message' longtext COLLATE utf8_unicode_ci,
  'created_at' datetime NOT NULL,
  'updated_at' datetime NOT NULL,
  'max_duration' int(11) DEFAULT NULL,
  'run_id' bigint(20) DEFAULT NULL,
  'stalls' int(11) NOT NULL,
  'max_stalls' int(11) DEFAULT NULL,
  'exceptions' int(11) NOT NULL,
  'max_exceptions' int(11) DEFAULT NULL,
  'failures' int(11) NOT NULL,
  'max_failures' int(11) DEFAULT NULL,
  'retries' int(11) NOT NULL,
  'max_retries' int(11) DEFAULT NULL,
  PRIMARY KEY ('id'),
  KEY 'job_crc_hash_idx' ('crc_hash','status'),
  KEY 'job_priority_idx' ('priority','when_us'),
  KEY 'job_when_idx' ('when_us'),
  KEY 'job_status_idx' ('status','when_us')
) ENGINE=InnoDB AUTO_INCREMENT=145 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

3) Идентификаторы записей:

mysql> SELECT t0.id as id_1 FROM dtc_queue_job t0;
+------+
| id_1 |
+------+
|  123 |
|  124 |
|  125 |
|  126 |
|  127 |
|  128 |
|  129 |
|  130 |
|  131 |
|  132 |
|  133 |
|  134 |
|   20 |
|   21 |
|   22 |
|   23 |
|   24 |
|   25 |
|   26 |
|   27 |
|   28 |
|   29 |
|   30 |
|   31 |
|   32 |
|   33 |
|   34 |
|   35 |
|   36 |
|   37 |
|   38 |
|   39 |
|   40 |
|   41 |
|   42 |
|   43 |
|   44 |
|   45 |
|   46 |
|   47 |
|   48 |
|   49 |
|   50 |
|   51 |
|   52 |
|   53 |
|   54 |
|   55 |
|   56 |
|   57 |
|   58 |
|   59 |
|   60 |
|   61 |
|   62 |
|   63 |
|   64 |
|   65 |
|   66 |
|   67 |
|   68 |
|   69 |
|   70 |
|   71 |
|   72 |
|   73 |
|   74 |
|   75 |
|   76 |
|   77 |
|   78 |
|   79 |
|   80 |
|   81 |
|   82 |
|   83 |
|   84 |
|   85 |
|   86 |
|   87 |
|   88 |
|   89 |
|   90 |
|   91 |
|   92 |
|   93 |
|   94 |
|   95 |
|   96 |
|   97 |
|   98 |
|   99 |
|  100 |
|  101 |
|  102 |
|  103 |
|  104 |
|  105 |
|  106 |
|  107 |
|  108 |
|  109 |
|  110 |
|  111 |
|  112 |
|  113 |
|  114 |
|  115 |
|  116 |
|  117 |
|  118 |
|  119 |
+------+
112 rows in set (0.00 sec)

4) Дополнительная информация:

MySQL загружен с официального изображения докеров:

root@baf5881b2eb2:/# mysql --version
mysql  Ver 14.14 Distrib 5.7.19, for Linux (x86_64) using  EditLine wrapper
root@baf5881b2eb2:/# mysqld --version
mysqld  Ver 5.7.19 for Linux on x86_64 (MySQL Community Server (GPL))
Теги:

1 ответ

1
Лучший ответ

Не имеет смысла использовать LIMIT или OFFSET без указания заказа для вашего набора результатов. Обычно это делается с помощью предложения ORDER BY. Основная идея здесь состоит в том, что вам нужно сказать MySQL, чтобы взять первые 12 записей относительно упорядочения некоторого столбца.

Обратите внимание: внутри таблицы MySQL нет внутреннего порядка, поэтому, если вы не укажете порядок, то нет гарантии, что порядок записей, который вы получите, будет одинаковым с каждым запросом. Это может быть, но опять-таки этого может и не быть.

Если вы выполняете следующий запрос несколько раз, я ожидаю, что вы получите тот же набор результатов, если базовые данные не будут меняться между запросами:

SELECT
    id,
    max_retries
FROM dtc_queue_job
WHERE
    status = 'running'
ORDER BY id
LIMIT 12 OFFSET 100;

Здесь мы берем первые 12 записей, смещенных на 100, относительно столбца id.

  • 0
    Интересно, вы правы, что, кажется, дает последовательные результаты.
  • 0
    @mmucklo Двигаясь вперед, вам, вероятно, следует всегда использовать ORDER BY если вы используете LIMIT , если вам действительно все равно, что вы получите.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню