Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Bisakah MySQL FIND_IN_SET atau yang setara dibuat menggunakan indeks?

Mengacu pada komentar Anda:

@MarcB database dinormalisasi, string CSV berasal dari UI."Dapatkan saya data untuk orang-orang berikut:101,202,303"

Jawaban ini memiliki fokus yang sempit hanya pada angka-angka yang dipisahkan oleh koma. Karena, ternyata, Anda bahkan tidak membicarakan FIND_IN_SET bagaimanapun juga.

Ya, Anda dapat mencapai apa yang Anda inginkan. Anda membuat pernyataan siap yang menerima string sebagai parameter seperti dalam Jawaban Terbaru ini saya. Pada jawaban tersebut, lihat blok kedua yang menunjukkan CREATE PROCEDURE dan parameter ke-2 yang menerima string seperti (1,2,3) . Saya akan kembali ke titik ini sebentar lagi.

Bukan berarti Anda perlu melihatnya @spraff tetapi yang lain mungkin. Misinya adalah untuk mendapatkan type !=SEMUA, dan possible_keys dan keys dari Jelaskan untuk tidak menunjukkan nol, seperti yang Anda tunjukkan di blok kedua Anda. Untuk bacaan umum tentang topik ini, lihat artikel Memahami JELASKAN Keluaran dan Halaman Manual MySQL berjudul MENJELASKAN Informasi Tambahan .

Sekarang, kembali ke (1,2,3) referensi di atas. Kami tahu dari komentar Anda, dan keluaran Jelaskan kedua Anda dalam pertanyaan Anda bahwa itu mencapai kondisi yang diinginkan berikut:

  1. type =range (dan khususnya bukan SEMUA) . Lihat dokumen di atas tentang ini.
  2. kunci bukan nol

Ini persis kondisi yang Anda miliki dalam output Jelaskan kedua Anda, dan output yang dapat dilihat dengan kueri berikut:

explain 
select * from ratings where id in (2331425, 430364, 4557546, 2696638, 4510549, 362832, 2382514, 1424071, 4672814, 291859, 1540849, 2128670, 1320803, 218006, 1827619, 3784075, 4037520, 4135373, ... use your imagination ..., ...,  4369522, 3312835);

di mana saya memiliki 999 nilai dalam in daftar klausa. Itu adalah contoh dari jawaban ini milik saya di Lampiran D daripada menghasilkan string csv acak, dikelilingi oleh tanda kurung buka dan tutup.

Dan perhatikan berikut ini. Jelaskan output untuk elemen 999 itu dalam klausa di bawah ini:

Tujuan tercapai. Anda mencapai ini dengan proc tersimpan yang mirip dengan yang saya sebutkan sebelumnya di tautan ini menggunakan PREPARED STATEMENT (dan hal-hal itu menggunakan concat() diikuti oleh EXECUTE ).

Indeks yang digunakan, Tablescan (artinya buruk) tidak berpengalaman. Bacaan lebih lanjut adalah Jenis Gabung Rentang , referensi apa pun yang dapat Anda temukan di Pengoptimal Berbasis Biaya (CBO) MySQL, jawaban ini dari vladr meskipun tanggal, dengan memperhatikan ANALYZE TABLE bagian, khususnya setelah perubahan data yang signifikan. Perhatikan bahwa ANALYZE dapat memakan banyak waktu untuk dijalankan pada kumpulan data yang sangat besar. Terkadang berjam-jam.

Serangan Injeksi Sql:

Penggunaan string yang diteruskan ke Stored Procedures adalah vektor serangan untuk serangan SQL Injection. Tindakan pencegahan harus dilakukan untuk mencegahnya saat menggunakan data yang disediakan pengguna. Jika rutinitas Anda diterapkan terhadap id Anda sendiri yang dihasilkan oleh sistem Anda, maka Anda aman. Namun, perhatikan bahwa serangan SQL Injection tingkat 2 terjadi saat data ditempatkan oleh rutinitas yang tidak membersihkan data tersebut dalam penyisipan atau pembaruan sebelumnya. Serangan dilakukan sebelumnya melalui data dan digunakan kemudian (semacam bom waktu).

Jadi jawaban ini Selesai sebagian besar.

Di bawah ini adalah tampilan tabel yang sama dengan sedikit modifikasi untuk menunjukkan pemindaian Tabel yang ditakuti akan terlihat seperti di kueri sebelumnya (tetapi terhadap kolom yang tidak diindeks bernama thing ).

Lihatlah definisi tabel kami saat ini:

CREATE TABLE `ratings` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `thing` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5046214 DEFAULT CHARSET=utf8;

select min(id), max(id),count(*) as theCount from ratings;
+---------+---------+----------+
| min(id) | max(id) | theCount |
+---------+---------+----------+
|       1 | 5046213 |  4718592 |
+---------+---------+----------+

Perhatikan bahwa kolom thing adalah kolom int nullable sebelumnya.

update ratings set thing=id where id<1000000;
update ratings set thing=id where id>=1000000 and id<2000000;
update ratings set thing=id where id>=2000000 and id<3000000;
update ratings set thing=id where id>=3000000 and id<4000000;
update ratings set thing=id where id>=4000000 and id<5100000;
select count(*) from ratings where thing!=id;
-- 0 rows

ALTER TABLE ratings MODIFY COLUMN thing int not null;

-- current table definition (after above ALTER):
CREATE TABLE `ratings` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `thing` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5046214 DEFAULT CHARSET=utf8;

Dan kemudian Jelaskan bahwa itu adalah Pemindaian Tabel (terhadap kolom thing ):




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bagaimana menemukan peringkat ke-n di MySQL?

  2. SQL Query untuk menunjukkan tanggal terdekat?

  3. Cara membuat kueri bergabung menggunakan Sequelize di Node.js

  4. 1114 (HY000):Meja sudah penuh

  5. JSON_MERGE_PATCH() – Lakukan Penggabungan Dokumen JSON yang Sesuai dengan RFC 7396 di MySQL