Die Datenmenge ist zu groß und die Paging-Abfrage wird langsam. Gibt es eine Möglichkeit, die Abfrage zu optimieren?

WBOY
Freigeben: 2016-08-04 09:20:00
Original
2969 Leute haben es durchsucht

Da es zu viele Benutzerdatensätze gibt (3 Millionen), wird die Paging-Abfrage sehr langsam. Wie kann die Anweisung oder der Index optimiert werden? Haben Sie Optimierungspläne?

Ergänzender Inhalt:
Vielen Dank an alle für Ihre Lösung. Ich bin davon sehr inspiriert, aber sie ist in meiner Situation etwas ganz Besonderes und nicht anwendbar. Die konkrete Situation ist wie folgt:
1 Wenn der Benutzer die Seite mit den Teilnahmedatensätzen öffnet, sollten die Datensätze der letzten 10 Teilnehmer angezeigt werden. (Bei den Datensätzen dieser 10 Personen handelt es sich nicht um die neuesten zehn Daten in der Tabelle der Benutzerbeteiligungsdatensätze, sondern um die zehn Daten, die durch Hinzufügen von WHERE-Bedingungen herausgefiltert wurden.)
2 Die neuesten Daten der 10 teilnehmenden Personen werden den beiden Tabellen entnommen Erhalten Sie (Benutzerinformationstabelle, Benutzerbeteiligungsdatensatztabelle).
3 Stellen Sie sicher, dass Benutzer zur nächsten Datenseite und zur vorherigen Datenseite wechseln können.
Das Abfragen von Daten besteht nun darin, zwei Tabellen zu verbinden, die Bedingungen der beiden Tabellen zu ermitteln und dann die Daten einzuschränken. Das ist zu langsam, daher würde ich gerne fragen, ob es Optimierungslösungen gibt?

Antwortinhalt:

Da es zu viele Benutzerdatensätze gibt (3 Millionen), wird die Paging-Abfrage sehr langsam. Wie kann die Anweisung oder der Index optimiert werden? Haben Sie Optimierungspläne?

Ergänzender Inhalt:
Vielen Dank an alle für Ihre Lösung. Ich bin davon sehr inspiriert, aber sie ist in meiner Situation etwas ganz Besonderes und nicht anwendbar. Die konkrete Situation ist wie folgt:
1 Wenn der Benutzer die Seite mit den Teilnahmedatensätzen öffnet, sollten die Datensätze der letzten 10 Teilnehmer angezeigt werden. (Bei den Datensätzen dieser 10 Personen handelt es sich nicht um die neuesten zehn Daten in der Tabelle der Benutzerbeteiligungsdatensätze, sondern um die zehn Daten, die durch Hinzufügen von WHERE-Bedingungen herausgefiltert wurden.)
2 Die neuesten Daten der 10 teilnehmenden Personen werden den beiden Tabellen entnommen Erhalten Sie (Benutzerinformationstabelle, Benutzerbeteiligungsdatensatztabelle).
3 Stellen Sie sicher, dass Benutzer zur nächsten Datenseite und zur vorherigen Datenseite wechseln können.
Das Abfragen von Daten besteht nun darin, zwei Tabellen zu verbinden, die Bedingungen der beiden Tabellen zu ermitteln und dann die Daten einzuschränken. Das ist zu langsam, daher würde ich gerne fragen, ob es Optimierungslösungen gibt?

1. Verwenden Sie kein Limit, ohne Bedingungen von 0 bis 10002 hinzuzufügen.
2 Merken Sie sich den letzten Benutzer-Primärschlüssel und verwenden Sie „select * from user“ für Paging. lastUid-Limit-Seitengröße
3. Die Anforderungen an die Datenkonsistenz sind nicht hoch. Erwägen Sie das Hinzufügen einer Cache-Ebene in der Mitte der Datenbank

<code class="sql">EXPLAIN SELECT * FROM lagou where id <=100</code>
Nach dem Login kopieren

Die Datenmenge ist zu groß und die Paging-Abfrage wird langsam. Gibt es eine Möglichkeit, die Abfrage zu optimieren?

<code class="sql">EXPLAIN SELECT * FROM lagou LIMIT 100</code>
Nach dem Login kopieren

Die Datenmenge ist zu groß und die Paging-Abfrage wird langsam. Gibt es eine Möglichkeit, die Abfrage zu optimieren?

HinweisTyp einer ist „Bereich“ und der andere ist „alle“

Zusammenfassung: Was für eine schmerzhafte Erkenntnis~

MySQL LIMIT-Paging-Optimierung (wobei id der automatisch inkrementierte Primärschlüssel der Beitragstabelle ist):
SELECT * FROM posts ORDER BY id DESC LIMIT 20 OFFSET 10000
Scannen Sie 10020 Zeilen, überspringen Sie die ersten 10000 Zeilen und geben Sie die letzten 20 Zeilen zurück ist langsam.
Ein besseres Design besteht darin, die spezifische Anzahl von Seiten durch die Schaltfläche „Nächste Seite“ zu ersetzen.
Angenommen, jede Seite zeigt 20 Datensätze an. Dann gibt LIMIT bei jeder Abfrage 21 Datensätze zurück und zeigt nur 20 an .
Wenn Element 21 vorhanden ist, zeigen wir die Schaltfläche „Nächste Seite“ oder „AJAX Mehr laden“ an.

Verwenden Sie „vorherige Seite“ und „nächste Seite“ zum Blättern:
Vorherige Seite (id: 60~41)
Aktuelle Seite (id: 40~21)
Nächste Seite (id:20~ 01)

Vorherige Seite (20 neue Artikel):
//page.php?id=40 Eine positive Zahl zeigt einen neuen Artikel auf der vorherigen Seite an, und 40 gibt hier die ID des Top-Artikels auf der aktuellen Seite an.
SELECT * FROM posts WHERE id > 40 ORDER BY id ASC LIMIT 20;
Was Sie hier erhalten, ist die aufsteigende ID-Sequenz. PHP kann array_reverse verwenden, um das Array umzukehren, um eine absteigende Ausgabe zu erzielen.

Nächste Seite (20 alte Artikel):
//page.php?id=-21 Eine negative Zahl gibt den alten Artikel auf der nächsten Seite an, und 21 gibt hier die ID des untersten Artikels auf der aktuellen Seite an .
SELECT * FROM posts WHERE id < 21 ORDER BY id DESC LIMIT 20;
Wenn Sie der Meinung sind, dass negative Zahlen nicht gut aussehen, können Sie einen zusätzlichen Parameter hinzufügen, z. B. page.php?id=21&next

Ich persönlich denke, dass dies eine Paging-Abfrageoptimierung ist, bei der es sich lediglich um eine Paginierung nach dem Zusammenführen zweier Tabellen handelt

Typische Paginierungsoptimierung ist:

Normales Schreiben:

<code>select * from buyer where sellerid=100 limit 100000,20</code>
Nach dem Login kopieren

Die allgemeine Methode zum Umblättern von M und N ist langsamer, wenn die Seite weiter zurückgeblättert wird. Der Grund dafür ist, dass MySQL die ersten M N-Daten in der Tabelle liest. Je größer M, desto schlechter ist die Leistung

Optimiertes Schreiben:

<code>select t1.* from buyer t1, (select id from buyer where sellerid=100 limit 100000,20 ) t2 where t1.id=t2.id</code>
Nach dem Login kopieren
Sie müssen einen Index im Feld sellerid in der t-Tabelle erstellen, und id ist der Primärschlüssel der Tabelle

如果id主键是自增且连续的(未出现删除记录)那么可以改用where between

假设user_id是自增主键

<code class="sql">SELECT * FROM user
WHERE user_id >= (
SELECT user_id FROM user
LIMIT pageIndex, 1
)
LIMIT pageSize;</code></p>
Nach dem Login kopieren

参考:https://mp.weixin.qq.com/s?__biz=MjM5NzMyMjAwMA==&mid=2651477279&idx=1&sn=4a799a4aa2f8563d482973e262e906b8&scene=1&srcid=0629Qe4RKqmpBhwOUzFJeK1B&key=77421cf58af4a65302d0d5987b2f5d1610469f10ba9f2ac129747c2578d1a68463e33f8c7f388537de80a7bc38d00c05&ascene=0&uin=ODYxODM1MDE4&devicetype=iMac+MacBookAir6%2C2+OSX+OSX+10.9.5+build(13F34)&version=11020012&pass_ticket=aZDru5jCHRXbpBvmRG0m%2BkUwb4sJZ2hIfzTt6LDC1xnW2ZMj0mgDjwuyZgisQJxA

请根据自己的查询条件定义where子句,同时不要反复count记录数量。
1- 记忆当前页的最后一条记录,下次查询的时候根据order by添加对应的where子句代替跳过N行
2- 数据量大的时候总共多少页在实际使用的时候已经失去意义,但是count的消耗却很大,确实需要的话首次查询时获得一次就好了。

同意楼上的意见

1.完善搜索及索引建立
2.设计数据表默认排序作为排序规则,降低查询排序耗时
3.在id为有序数字情况下,利用最后一次id作为下一次检索条件,极大降低返回数据集
4.减少count的次数和精度,超大数据可以缓存count值
5.更大型数据可根据分页规则、类型等对数据表进行拆分,降低单次查询数据量

1 你减少sql语句的函数使用
2 减少order by 和group by
3 对查询条件的字段添加索引
4 300w的记录应该操作记录,不是实时需要展示的数据,那么可以做数据缓存。
5 js使用$(obj).load("url #id") 进行ajax局部刷新翻页,这样可以避免你的资源重新加载
我知道的就这么多了

按我的理解你的情况是限制条件在用户参与记录表中,而用户信息表实际上只要按前一个表的id取数据就可以了。我估计你索引已经做了,剩下能有大的改观的就是数据分区和预排序,参与记录表按主要查询条件,用户信息表按id分区。然后参与记录表一定要预排序,如果到查询时再排序,再怎么样也快不起来。

增加where条件 主键>0 然后只取主键,这个是分页用,取内容用 where IN 直接取主键,比你查的快多了

把某个用户的信息缓存,分页查询就查用户参与记录表

两张表关联,而且显示最新参与的10个人的记录。这样关联的时候,查询的sql会现的复杂。所以建议通过两条sql+php的遍历实现。查询需要的个人记录一个sql,查询会员一个sql,然后遍历数组生成需要的数组。总之就是将复杂的sql拆分成简单的sql

建立合适的索引
查询先分页主键,然后通过主键结果查内容 曾经做过7kw的日志数据查询,分页很快的。

对数据实效性要求不高的话 可以用sphinx做查询

limit 基数比较大时使用 between , 取比较后面的数据时用 desc 反向查找 .

可以写个定时脚本,10分钟跑一次这样的,将取到的数据保存起来,用户打开页面时就从这个表里取。只是展示最新参与的话,来个几分钟的延迟应该是可以接受的

Überprüfen Sie zunächst sorgfältig, ob Ihr SQL Raum für Optimierung bietet. Erwägen Sie dann die Optimierung der Datenbank, das Caching und die Trennung von Lesen und Schreiben.

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage