Хорошие методы индексации для производительности в mysql базах данных - PullRequest
0 голосов
/ 28 января 2020

Я собираюсь развернуть веб-приложение, которое может закончиться довольно большой базой данных и у меня есть некоторые сомнения, которые я хотел бы прояснить перед началом работы.

Немного объясню мои настройки и большинство общие запросы:

1 - я использую sqlalchemy

2 - у меня много разных таблиц, на которые ссылается их идентификатор (целочисленное уникальное поле)

3 - в некоторых таблицах используется столбец со случайной уникальной строкой в ​​50 символов, которую я использую на стороне клиента, чтобы не показывать идентификатор клиентам. Этот столбец проиндексирован.

4- Я также проиндексировал некоторые столбцы даты и времени, которые я использую для запросов, которые находят строки в диапазонах дат.

5 - Все отношения индексируются, потому что иногда я запрашиваю по этому параметру .

6 - Также проиндексированы некоторые столбцы Bool, которые я запрашиваю вместе с другим столбцом индекса.

Итак, помня об этом, я спрашиваю:

В пункте 3: Это нормально сделать запрос по этой уникальной индексированной строке 50 символов? Это не слишком долго, чтобы работать в качестве индекса? Будет ли работать теперь так же быстро, как и с регистром 50 миллионов?

Пример запроса:

customer=users.query.filter_by(secretString="ZT14V-_hD9qZrtwLj-rLPTioWQ1MJ4rhfqCUx8SvF0BrrCLtgvV_ZVXXV8_xXW").first()

Затем я использую этот запрос пользователя, чтобы найти связанный с ним объект:

associatedObject=objects.query.filter_by(id=customer.associatedObject).first()

Поэтому, когда у меня есть эти результаты, я просто получаю от них все, что мне нужно:

return({"username":user.Name,"AssociatedStuff":associatedObject.Name})

О пункте 4:

Будут ли работать эти индексы в столбцах даты и времени при сравнении с операторами <>?

О пункте 6:

Можно запросить что-то вроде: userFineshedTasks=tasks.query.filter(task.completed==True, task.userID==user.id).all() завершено, а userID проиндексировал столбцы и userID ссылка на столбец идентификатора пользователя. «Обратите внимание, что этот запрос не имеет смысла, потому что я могу получить выполненную пользователем задачу из user.tasks.all (), если на нее есть ссылки и отфильтровать выполненную оттуда, но так же, как пример запроса ...»

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

Надеюсь, кто-то может позволить мне знать, является ли это хорошей практикой или у меня будут проблемы с производительностью в будущем. Заранее спасибо!

@ Рик Джеймс: Здесь я выкладываю код создания таблицы sql из файла экспорта базы данных: надеюсь, этого достаточно, чтобы получить представление, это пример одной из таблиц, в основном те же идеи, которые применимы к моим вопросам.

CREATE TABLE `Bookings` ( `id` int(11) NOT NULL, `CodigoAlojamiento` int(11) DEFAULT NULL, `Entrada` datetime DEFAULT NULL, `Salida` datetime DEFAULT NULL, `Habitaciones` longtext COLLATE utf8_unicode_ci, `Precio` float DEFAULT NULL, `Agencia` varchar(500) COLLATE utf8_unicode_ci DEFAULT NULL, `Extras` text COLLATE utf8_unicode_ci, `Confirmada` tinyint(1) DEFAULT NULL, `NumeroOcupantes` int(11) DEFAULT NULL, `Completada` tinyint(1) DEFAULT NULL, `Tarifa` int(11) DEFAULT NULL, `SafeURL` varchar(120) COLLATE utf8_unicode_ci DEFAULT NULL, `EmailContacto` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL, `TelefonoContacto` varchar(30) COLLATE utf8_unicode_ci DEFAULT NULL, `Titular` varchar(300) COLLATE utf8_unicode_ci DEFAULT NULL, `Observaciones` text COLLATE utf8_unicode_ci, `IdentificadorReserva` varchar(500) COLLATE utf8_unicode_ci DEFAULT NULL, `Facturada` tinyint(1) DEFAULT NULL, `FacturarAClienteOAgencia` varchar(1) COLLATE utf8_unicode_ci DEFAULT NULL, `Pagada` tinyint(1) DEFAULT NULL, `CheckOut` tinyint(1) DEFAULT NULL, `PagaClienteOAgencia` char(1) COLLATE utf8_unicode_ci DEFAULT NULL, `NumeroFactura` int(11) DEFAULT NULL, `FechaFactura` datetime DEFAULT NULL, `CheckIn` tinyint(1) DEFAULT NULL, `EsPreCheckIn` tinyint(1) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

вот индексы:

ALTER TABLE `Bookings`
  ADD PRIMARY KEY (`id`),
  ADD UNIQUE KEY `ix_Bookings_SafeURL` (`SafeURL`),
  ADD KEY `ix_Bookings_CodigoAlojamiento` (`CodigoAlojamiento`),
  ADD KEY `ix_Bookings_Tarifa` (`Tarifa`),
  ADD KEY `ix_BookingsE_CheckIn` (`CheckIn`),
  ADD KEY `ix_Bookings_CheckOut` (`CheckOut`),
  ADD KEY `ix_Bookings_Completada` (`Completada`),
  ADD KEY `ix_Bookings_Confirmada` (`Confirmada`),
  ADD KEY `ix_Bookings_Entrada` (`Entrada`),
  ADD KEY `ix_Bookings_EsPreCheckIn` (`EsPreCheckIn`),
  ADD KEY `ix_Bookings_Salida` (`Salida`);```

And here the references:

```ALTER TABLE `Bookings`
  ADD CONSTRAINT `Bookings_ibfk_1` FOREIGN KEY (`CodigoAlojamiento`) REFERENCES `Alojamientos` (`id`),
  ADD CONSTRAINT `Bookings_ibfk_2` FOREIGN KEY (`Tarifa`) REFERENCES `Tarifas` (`id`);```

1 Ответ

1 голос
/ 28 января 2020
  • 4 - для запросов, которые находят строки в диапазонах дат.

Обычно в WHERE есть что-то еще, скажем,

 WHERE x = 123
   AND Entrada BETWEEN ... AND ...

В этом случае это оптимально: INDEX(x, Entrada)

`CheckOut` tinyint(1) DEFAULT NULL
ADD KEY `ix_Bookings_CheckOut` (`CheckOut`),
  • Редко полезно индексировать «флаг». Однако составной индекс (как указано выше) может быть полезен.

  • Почему большинство столбцов NULLable? Для «логических значений» просто используйте 0 и 1 и DEFAULT в зависимости от того, какой из них подходит. Используйте NULL для «не знаю», «необязательно», «еще не предоставлено» и т. Д. c.

  • 6 - также проиндексированы некоторые столбцы Bool, которые я запрашиваю вместе с другим столбцом индекса.

Затем составьте индекс. И обязательно говорите b=1, а не b<>0, так как <> также не оптимизирует.

  • Можно запросить эту уникальную индексированную строку из 50 символов? Это не слишком долго, чтобы работать в качестве индекса? Будет ли работать теперь так же быстро, как и с регистром 50 миллионов?

Если набор данных становится больше ОЗУ, возникает проблема производительности со «случайными» индексами. Ваш пример должен быть в порядке. (Лично я думаю, что 50 символов являются чрезмерными.) И такой 'ha sh', вероятно, должен быть CHARACTER SET ascii и, возможно, с COLLATE ascii_bin вместо версии со складыванием регистра.

  • И "task.completed == True, task.userID == user.id", вероятно, лучше всего индексировать с помощью "составного" INDEX(userID, completed) в любом порядке.

  • Да, Индексы в столбцах datetime делают некоторую работу при сравнении с операторами <, <=,>,> =? Строки также можно сравнивать, хотя я не вижу вероятных столбцов для сравнения строк, кроме как с =.

  • 50M строк - это большой, но не "огромный". Составные индексы часто важны для больших таблиц.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...